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