View Javadoc

1   package org.apache.maven.doxia.sink;
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.ByteArrayOutputStream;
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.OutputStream;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import org.apache.maven.doxia.logging.Log;
31  
32  /**
33   * The RandomAccessSink provides the ability to create a {@link Sink} with hooks.
34   * A page can be prepared by first creating its structure and specifying the positions of these hooks.
35   * After specifying the structure, the page can be filled with content from one or more models.
36   * These hooks can prevent you to have to loop over the model multiple times to build the page as desired. 
37   * 
38   * @author Robert Scholte
39   * @since 1.3
40   */
41  public class RandomAccessSink
42      implements Sink
43  {
44      private SinkFactory sinkFactory;
45  
46      private String encoding;
47  
48      private OutputStream coreOutputStream;
49  
50      private Sink coreSink;
51  
52      private List<Sink> sinks = new ArrayList<Sink>();
53  
54      private List<ByteArrayOutputStream> outputStreams = new ArrayList<ByteArrayOutputStream>();
55  
56      private Sink currentSink;
57  
58      public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream )
59          throws IOException
60      {
61          this.sinkFactory = sinkFactory;
62          this.coreOutputStream = stream;
63          this.coreSink = this.currentSink = sinkFactory.createSink( stream );
64      }
65  
66      public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding )
67          throws IOException
68      {
69          this.sinkFactory = sinkFactory;
70          this.coreOutputStream = stream;
71          this.encoding = encoding;
72          this.coreSink = this.currentSink = sinkFactory.createSink( stream, encoding );
73      }
74  
75      public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName )
76          throws IOException
77      {
78          this.sinkFactory = sinkFactory;
79          this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
80          this.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream );
81      }
82  
83      public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName, String encoding )
84          throws IOException
85      {
86          this.sinkFactory = sinkFactory;
87          this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
88          this.encoding = encoding;
89          this.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream, encoding );
90      }
91  
92      /**
93       * By calling this method a sink reference is added at the current position. You can write to both the new sink
94       * reference and the original sink. After flushing all sinks will be flushed in the right order.
95       * 
96       * @return a subsink reference you can write to
97       */
98      public Sink addSinkHook()
99      {
100         Sink subSink = null;
101         try
102         {
103             ByteArrayOutputStream subOut = new ByteArrayOutputStream();
104             ByteArrayOutputStream newOut = new ByteArrayOutputStream();
105 
106             outputStreams.add( subOut );
107             outputStreams.add( newOut );
108 
109             if ( encoding != null )
110             {
111                 subSink = sinkFactory.createSink( subOut, encoding );
112                 currentSink = sinkFactory.createSink( newOut, encoding );
113             }
114             else
115             {
116                 subSink = sinkFactory.createSink( subOut );
117                 currentSink = sinkFactory.createSink( newOut );
118             }
119             sinks.add( subSink );
120             sinks.add( currentSink );
121         }
122         catch ( IOException e )
123         {
124             // IOException can only be caused by our own ByteArrayOutputStream
125         }
126         return subSink;
127     }
128 
129     /** {@inheritDoc} */
130     public void anchor( String name )
131     {
132         currentSink.anchor( name );
133     }
134 
135     /** {@inheritDoc} */
136     public void anchor( String name, SinkEventAttributes attributes )
137     {
138         currentSink.anchor( name, attributes );
139     }
140 
141     /** {@inheritDoc} */
142     public void anchor_()
143     {
144         currentSink.anchor_();
145     }
146 
147     /** {@inheritDoc} */
148     public void author()
149     {
150         currentSink.author();
151     }
152 
153     /** {@inheritDoc} */
154     public void author( SinkEventAttributes attributes )
155     {
156         currentSink.author( attributes );
157     }
158 
159     /** {@inheritDoc} */
160     public void author_()
161     {
162         currentSink.author_();
163     }
164 
165     /** {@inheritDoc} */
166     public void body()
167     {
168         currentSink.body();
169     }
170 
171     /** {@inheritDoc} */
172     public void body( SinkEventAttributes attributes )
173     {
174         currentSink.body( attributes );
175     }
176 
177     /** {@inheritDoc} */
178     public void body_()
179     {
180         currentSink.body_();
181     }
182 
183     /** {@inheritDoc} */
184     public void bold()
185     {
186         currentSink.bold();
187     }
188 
189     /** {@inheritDoc} */
190     public void bold_()
191     {
192         currentSink.bold_();
193     }
194 
195     /**
196      * Close all sinks
197      */
198     public void close()
199     {
200         for ( Sink sink  : sinks )
201         {
202             // sink is responsible for closing it's stream
203             sink.close();
204         }
205         coreSink.close();
206     }
207 
208     /** {@inheritDoc} */
209     public void comment( String comment )
210     {
211         currentSink.comment( comment );
212     }
213 
214     /** {@inheritDoc} */
215     public void date()
216     {
217         currentSink.date();
218     }
219 
220     /** {@inheritDoc} */
221     public void date( SinkEventAttributes attributes )
222     {
223         currentSink.date( attributes );
224     }
225 
226     /** {@inheritDoc} */
227     public void date_()
228     {
229         currentSink.date_();
230     }
231 
232     /** {@inheritDoc} */
233     public void definedTerm()
234     {
235         currentSink.definedTerm();
236     }
237 
238     /** {@inheritDoc} */
239     public void definedTerm( SinkEventAttributes attributes )
240     {
241         currentSink.definedTerm( attributes );
242     }
243 
244     /** {@inheritDoc} */
245     public void definedTerm_()
246     {
247         currentSink.definedTerm_();
248     }
249 
250     /** {@inheritDoc} */
251     public void definition()
252     {
253         currentSink.definition();
254     }
255 
256     /** {@inheritDoc} */
257     public void definition( SinkEventAttributes attributes )
258     {
259         currentSink.definition( attributes );
260     }
261 
262     /** {@inheritDoc} */
263     public void definitionList()
264     {
265         currentSink.definitionList();
266     }
267 
268     /** {@inheritDoc} */
269     public void definitionList( SinkEventAttributes attributes )
270     {
271         currentSink.definitionList( attributes );
272     }
273 
274     /** {@inheritDoc} */
275     public void definitionListItem()
276     {
277         currentSink.definitionListItem();
278     }
279 
280     /** {@inheritDoc} */
281     public void definitionListItem( SinkEventAttributes attributes )
282     {
283         currentSink.definitionListItem( attributes );
284     }
285 
286     /** {@inheritDoc} */
287     public void definitionListItem_()
288     {
289         currentSink.definitionListItem_();
290     }
291 
292     /** {@inheritDoc} */
293     public void definitionList_()
294     {
295         currentSink.definitionList_();
296     }
297 
298     /** {@inheritDoc} */
299     public void definition_()
300     {
301         currentSink.definition_();
302     }
303 
304     /** {@inheritDoc} */
305     public void figure()
306     {
307         currentSink.figure();
308     }
309 
310     /** {@inheritDoc} */
311     public void figure( SinkEventAttributes attributes )
312     {
313         currentSink.figure( attributes );
314     }
315 
316     /** {@inheritDoc} */
317     public void figureCaption()
318     {
319         currentSink.figureCaption();
320     }
321 
322     /** {@inheritDoc} */
323     public void figureCaption( SinkEventAttributes attributes )
324     {
325         currentSink.figureCaption( attributes );
326     }
327 
328     /** {@inheritDoc} */
329     public void figureCaption_()
330     {
331         currentSink.figureCaption_();
332     }
333 
334     /** {@inheritDoc} */
335     public void figureGraphics( String name )
336     {
337         currentSink.figureGraphics( name );
338     }
339 
340     /** {@inheritDoc} */
341     public void figureGraphics( String src, SinkEventAttributes attributes )
342     {
343         currentSink.figureGraphics( src, attributes );
344     }
345 
346     /** {@inheritDoc} */
347     public void figure_()
348     {
349         currentSink.figure_();
350     }
351 
352     /**
353      * Flush all sinks
354      */
355     public void flush()
356     {
357         for ( int i = 0; i < sinks.size(); i++ )
358         {
359             // first flush to get complete buffer
360             // sink is responsible for flushing it's stream
361             Sink sink = sinks.get( i );
362             sink.flush();
363 
364             ByteArrayOutputStream stream = outputStreams.get( i );
365             try
366             {
367                 coreOutputStream.write( stream.toByteArray() );
368             }
369             catch ( IOException e )
370             {
371                 // @todo
372             }
373         }
374         coreSink.flush();
375     }
376 
377     /** {@inheritDoc} */
378     public void head()
379     {
380         currentSink.head();
381     }
382 
383     /** {@inheritDoc} */
384     public void head( SinkEventAttributes attributes )
385     {
386         currentSink.head( attributes );
387     }
388 
389     /** {@inheritDoc} */
390     public void head_()
391     {
392         currentSink.head_();
393     }
394 
395     /** {@inheritDoc} */
396     public void horizontalRule()
397     {
398         currentSink.horizontalRule();
399     }
400 
401     /** {@inheritDoc} */
402     public void horizontalRule( SinkEventAttributes attributes )
403     {
404         currentSink.horizontalRule( attributes );
405     }
406 
407     /** {@inheritDoc} */
408     public void italic()
409     {
410         currentSink.italic();
411     }
412 
413     /** {@inheritDoc} */
414     public void italic_()
415     {
416         currentSink.italic_();
417     }
418 
419     /** {@inheritDoc} */
420     public void lineBreak()
421     {
422         currentSink.lineBreak();
423     }
424 
425     /** {@inheritDoc} */
426     public void lineBreak( SinkEventAttributes attributes )
427     {
428         currentSink.lineBreak( attributes );
429     }
430 
431     /** {@inheritDoc} */
432     public void link( String name )
433     {
434         currentSink.link( name );
435     }
436 
437     /** {@inheritDoc} */
438     public void link( String name, SinkEventAttributes attributes )
439     {
440         currentSink.link( name, attributes );
441     }
442 
443     /** {@inheritDoc} */
444     public void link_()
445     {
446         currentSink.link_();
447     }
448 
449     /** {@inheritDoc} */
450     public void list()
451     {
452         currentSink.list();
453     }
454 
455     /** {@inheritDoc} */
456     public void list( SinkEventAttributes attributes )
457     {
458         currentSink.list( attributes );
459     }
460 
461     /** {@inheritDoc} */
462     public void listItem()
463     {
464         currentSink.listItem();
465     }
466 
467     /** {@inheritDoc} */
468     public void listItem( SinkEventAttributes attributes )
469     {
470         currentSink.listItem( attributes );
471     }
472 
473     /** {@inheritDoc} */
474     public void listItem_()
475     {
476         currentSink.listItem_();
477     }
478 
479     /** {@inheritDoc} */
480     public void list_()
481     {
482         currentSink.list_();
483     }
484 
485     /** {@inheritDoc} */
486     public void monospaced()
487     {
488         currentSink.monospaced();
489     }
490 
491     /** {@inheritDoc} */
492     public void monospaced_()
493     {
494         currentSink.monospaced_();
495     }
496 
497     /** {@inheritDoc} */
498     public void nonBreakingSpace()
499     {
500         currentSink.nonBreakingSpace();
501     }
502 
503     /** {@inheritDoc} */
504     public void numberedList( int numbering )
505     {
506         currentSink.numberedList( numbering );
507     }
508 
509     /** {@inheritDoc} */
510     public void numberedList( int numbering, SinkEventAttributes attributes )
511     {
512         currentSink.numberedList( numbering, attributes );
513     }
514 
515     /** {@inheritDoc} */
516     public void numberedListItem()
517     {
518         currentSink.numberedListItem();
519     }
520 
521     /** {@inheritDoc} */
522     public void numberedListItem( SinkEventAttributes attributes )
523     {
524         currentSink.numberedListItem( attributes );
525     }
526 
527     /** {@inheritDoc} */
528     public void numberedListItem_()
529     {
530         currentSink.numberedListItem_();
531     }
532 
533     /** {@inheritDoc} */
534     public void numberedList_()
535     {
536         currentSink.numberedList_();
537     }
538 
539     /** {@inheritDoc} */
540     public void pageBreak()
541     {
542         currentSink.pageBreak();
543     }
544 
545     /** {@inheritDoc} */
546     public void paragraph()
547     {
548         currentSink.paragraph();
549     }
550 
551     /** {@inheritDoc} */
552     public void paragraph( SinkEventAttributes attributes )
553     {
554         currentSink.paragraph( attributes );
555     }
556 
557     /** {@inheritDoc} */
558     public void paragraph_()
559     {
560         currentSink.paragraph_();
561     }
562 
563     /** {@inheritDoc} */
564     public void rawText( String text )
565     {
566         currentSink.rawText( text );
567     }
568 
569     /** {@inheritDoc} */
570     public void section( int level, SinkEventAttributes attributes )
571     {
572         currentSink.section( level, attributes );
573     }
574 
575     /** {@inheritDoc} */
576     public void section1()
577     {
578         currentSink.section1();
579     }
580 
581     /** {@inheritDoc} */
582     public void section1_()
583     {
584         currentSink.section1_();
585     }
586 
587     /** {@inheritDoc} */
588     public void section2()
589     {
590         currentSink.section2();
591     }
592 
593     /** {@inheritDoc} */
594     public void section2_()
595     {
596         currentSink.section2_();
597     }
598 
599     /** {@inheritDoc} */
600     public void section3()
601     {
602         currentSink.section3();
603     }
604 
605     /** {@inheritDoc} */
606     public void section3_()
607     {
608         currentSink.section3_();
609     }
610 
611     /** {@inheritDoc} */
612     public void section4()
613     {
614         currentSink.section4();
615     }
616 
617     /** {@inheritDoc} */
618     public void section4_()
619     {
620         currentSink.section4_();
621     }
622 
623     /** {@inheritDoc} */
624     public void section5()
625     {
626         currentSink.section5();
627     }
628 
629     /** {@inheritDoc} */
630     public void section5_()
631     {
632         currentSink.section5_();
633     }
634 
635     /** {@inheritDoc} */
636     public void sectionTitle()
637     {
638         currentSink.sectionTitle();
639     }
640 
641     /** {@inheritDoc} */
642     public void sectionTitle( int level, SinkEventAttributes attributes )
643     {
644         currentSink.sectionTitle( level, attributes );
645     }
646 
647     /** {@inheritDoc} */
648     public void sectionTitle1()
649     {
650         currentSink.sectionTitle1();
651     }
652 
653     /** {@inheritDoc} */
654     public void sectionTitle1_()
655     {
656         currentSink.sectionTitle1_();
657     }
658 
659     /** {@inheritDoc} */
660     public void sectionTitle2()
661     {
662         currentSink.sectionTitle2();
663     }
664 
665     /** {@inheritDoc} */
666     public void sectionTitle2_()
667     {
668         currentSink.sectionTitle2_();
669     }
670 
671     /** {@inheritDoc} */
672     public void sectionTitle3()
673     {
674         currentSink.sectionTitle3();
675     }
676 
677     /** {@inheritDoc} */
678     public void sectionTitle3_()
679     {
680         currentSink.sectionTitle3_();
681     }
682 
683     /** {@inheritDoc} */
684     public void sectionTitle4()
685     {
686         currentSink.sectionTitle4();
687     }
688 
689     /** {@inheritDoc} */
690     public void sectionTitle4_()
691     {
692         currentSink.sectionTitle4_();
693     }
694 
695     /** {@inheritDoc} */
696     public void sectionTitle5()
697     {
698         currentSink.sectionTitle5();
699     }
700 
701     /** {@inheritDoc} */
702     public void sectionTitle5_()
703     {
704         currentSink.sectionTitle5_();
705     }
706 
707     /** {@inheritDoc} */
708     public void sectionTitle_()
709     {
710         currentSink.sectionTitle_();
711     }
712 
713     /** {@inheritDoc} */
714     public void sectionTitle_( int level )
715     {
716         currentSink.sectionTitle_( level );
717     }
718 
719     /** {@inheritDoc} */
720     public void section_( int level )
721     {
722         currentSink.section_( level );
723     }
724 
725     /** {@inheritDoc} */
726     public void table()
727     {
728         currentSink.table();
729     }
730 
731     /** {@inheritDoc} */
732     public void table( SinkEventAttributes attributes )
733     {
734         currentSink.table( attributes );
735     }
736 
737     /** {@inheritDoc} */
738     public void tableCaption()
739     {
740         currentSink.tableCaption();
741     }
742 
743     /** {@inheritDoc} */
744     public void tableCaption( SinkEventAttributes attributes )
745     {
746         currentSink.tableCaption( attributes );
747     }
748 
749     /** {@inheritDoc} */
750     public void tableCaption_()
751     {
752         currentSink.tableCaption_();
753     }
754 
755     /** {@inheritDoc} */
756     public void tableCell()
757     {
758         currentSink.tableCell();
759     }
760 
761     /** {@inheritDoc} */
762     public void tableCell( String width )
763     {
764         currentSink.tableCell( width );
765     }
766 
767     /** {@inheritDoc} */
768     public void tableCell( SinkEventAttributes attributes )
769     {
770         currentSink.tableCell( attributes );
771     }
772 
773     /** {@inheritDoc} */
774     public void tableCell_()
775     {
776         currentSink.tableCell_();
777     }
778 
779     /** {@inheritDoc} */
780     public void tableHeaderCell()
781     {
782         currentSink.tableHeaderCell();
783     }
784 
785     /** {@inheritDoc} */
786     public void tableHeaderCell( String width )
787     {
788         currentSink.tableHeaderCell( width );
789     }
790 
791     /** {@inheritDoc} */
792     public void tableHeaderCell( SinkEventAttributes attributes )
793     {
794         currentSink.tableHeaderCell( attributes );
795     }
796 
797     /** {@inheritDoc} */
798     public void tableHeaderCell_()
799     {
800         currentSink.tableHeaderCell_();
801     }
802 
803     /** {@inheritDoc} */
804     public void tableRow()
805     {
806         currentSink.tableRow();
807     }
808 
809     /** {@inheritDoc} */
810     public void tableRow( SinkEventAttributes attributes )
811     {
812         currentSink.tableRow( attributes );
813     }
814 
815     /** {@inheritDoc} */
816     public void tableRow_()
817     {
818         currentSink.tableRow_();
819     }
820 
821     /** {@inheritDoc} */
822     public void tableRows( int[] justification, boolean grid )
823     {
824         currentSink.tableRows( justification, grid );
825     }
826 
827     /** {@inheritDoc} */
828     public void tableRows_()
829     {
830         currentSink.tableRows_();
831     }
832 
833     /** {@inheritDoc} */
834     public void table_()
835     {
836         currentSink.table_();
837     }
838 
839     /** {@inheritDoc} */
840     public void text( String text )
841     {
842         currentSink.text( text );
843     }
844 
845     /** {@inheritDoc} */
846     public void text( String text, SinkEventAttributes attributes )
847     {
848         currentSink.text( text, attributes );
849     }
850 
851     /** {@inheritDoc} */
852     public void title()
853     {
854         currentSink.title();
855     }
856 
857     /** {@inheritDoc} */
858     public void title( SinkEventAttributes attributes )
859     {
860         currentSink.title( attributes );
861     }
862 
863     /** {@inheritDoc} */
864     public void title_()
865     {
866         currentSink.title_();
867     }
868 
869     /** {@inheritDoc} */
870     public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes )
871     {
872         currentSink.unknown( name, requiredParams, attributes );
873     }
874 
875     /** {@inheritDoc} */
876     public void verbatim( boolean boxed )
877     {
878         currentSink.verbatim( boxed );
879     }
880 
881     /** {@inheritDoc} */
882     public void verbatim( SinkEventAttributes attributes )
883     {
884         currentSink.verbatim( attributes );
885     }
886 
887     /** {@inheritDoc} */
888     public void verbatim_()
889     {
890         currentSink.verbatim_();
891     }
892 
893     /** {@inheritDoc} */
894     public void enableLogging( Log log )
895     {
896         currentSink.enableLogging( log );
897     }
898 }