blob: 62f6e07ba59108f28798aadce5698f6f3f79e6d2 [file] [log] [blame]
package org.apache.maven.doxia.sink.impl;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.doxia.logging.Log;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.sink.SinkFactory;
/**
* The RandomAccessSink provides the ability to create a {@link Sink} with hooks.
* A page can be prepared by first creating its structure and specifying the positions of these hooks.
* After specifying the structure, the page can be filled with content from one or more models.
* These hooks can prevent you to have to loop over the model multiple times to build the page as desired.
*
* @author Robert Scholte
* @since 1.3
*/
public class RandomAccessSink
implements Sink
{
private SinkFactory sinkFactory;
private String encoding;
private OutputStream coreOutputStream;
private Sink coreSink;
private List<Sink> sinks = new ArrayList<>();
private List<ByteArrayOutputStream> outputStreams = new ArrayList<>();
private Sink currentSink;
public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream )
throws IOException
{
this.sinkFactory = sinkFactory;
this.coreOutputStream = stream;
this.currentSink = sinkFactory.createSink( stream );
this.coreSink = this.currentSink;
}
public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding )
throws IOException
{
this.sinkFactory = sinkFactory;
this.coreOutputStream = stream;
this.encoding = encoding;
this.currentSink = sinkFactory.createSink( stream, encoding );
this.coreSink = this.currentSink;
}
public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName )
throws IOException
{
this.sinkFactory = sinkFactory;
this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
this.currentSink = sinkFactory.createSink( coreOutputStream );
this.coreSink = this.currentSink;
}
public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName, String encoding )
throws IOException
{
this.sinkFactory = sinkFactory;
this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
this.encoding = encoding;
this.currentSink = sinkFactory.createSink( coreOutputStream, encoding );
this.coreSink = this.currentSink;
}
@Override
public void address()
{
currentSink.address();
}
@Override
public void address( SinkEventAttributes attributes )
{
currentSink.address( attributes );
}
@Override
public void address_()
{
currentSink.address_();
}
/**
* By calling this method a sink reference is added at the current position. You can write to both the new sink
* reference and the original sink. After flushing all sinks will be flushed in the right order.
*
* @return a subsink reference you can write to
*/
public Sink addSinkHook()
{
Sink subSink = null;
try
{
ByteArrayOutputStream subOut = new ByteArrayOutputStream();
ByteArrayOutputStream newOut = new ByteArrayOutputStream();
outputStreams.add( subOut );
outputStreams.add( newOut );
if ( encoding != null )
{
subSink = sinkFactory.createSink( subOut, encoding );
currentSink = sinkFactory.createSink( newOut, encoding );
}
else
{
subSink = sinkFactory.createSink( subOut );
currentSink = sinkFactory.createSink( newOut );
}
sinks.add( subSink );
sinks.add( currentSink );
}
catch ( IOException e )
{
// IOException can only be caused by our own ByteArrayOutputStream
}
return subSink;
}
@Override
public void anchor( String name )
{
currentSink.anchor( name );
}
@Override
public void anchor( String name, SinkEventAttributes attributes )
{
currentSink.anchor( name, attributes );
}
@Override
public void anchor_()
{
currentSink.anchor_();
}
@Override
public void article()
{
currentSink.article();
}
@Override
public void article( SinkEventAttributes attributes )
{
currentSink.article( attributes );
}
@Override
public void article_()
{
currentSink.article_();
}
@Override
public void author()
{
currentSink.author();
}
@Override
public void author( SinkEventAttributes attributes )
{
currentSink.author( attributes );
}
@Override
public void author_()
{
currentSink.author_();
}
@Override
public void blockquote()
{
currentSink.blockquote();
}
@Override
public void blockquote( SinkEventAttributes attributes )
{
currentSink.blockquote( attributes );
}
@Override
public void blockquote_()
{
currentSink.blockquote_();
}
@Override
public void body()
{
currentSink.body();
}
@Override
public void body( SinkEventAttributes attributes )
{
currentSink.body( attributes );
}
@Override
public void body_()
{
currentSink.body_();
}
@Override
public void bold()
{
currentSink.bold();
}
@Override
public void bold_()
{
currentSink.bold_();
}
/**
* Close all sinks
*/
public void close()
{
for ( Sink sink : sinks )
{
// sink is responsible for closing it's stream
sink.close();
}
coreSink.close();
}
@Override
public void comment( String comment )
{
currentSink.comment( comment );
}
@Override
public void content()
{
currentSink.content();
}
@Override
public void content( SinkEventAttributes attributes )
{
currentSink.content( attributes );
}
@Override
public void content_()
{
currentSink.content_();
}
@Override
public void data( String value )
{
currentSink.data( value );
}
@Override
public void data( String value, SinkEventAttributes attributes )
{
currentSink.data( value, attributes );
}
@Override
public void data_()
{
currentSink.data_();
}
@Override
public void date()
{
currentSink.date();
}
@Override
public void date( SinkEventAttributes attributes )
{
currentSink.date( attributes );
}
@Override
public void date_()
{
currentSink.date_();
}
@Override
public void definedTerm()
{
currentSink.definedTerm();
}
@Override
public void definedTerm( SinkEventAttributes attributes )
{
currentSink.definedTerm( attributes );
}
@Override
public void definedTerm_()
{
currentSink.definedTerm_();
}
@Override
public void definition()
{
currentSink.definition();
}
@Override
public void definition( SinkEventAttributes attributes )
{
currentSink.definition( attributes );
}
@Override
public void definitionList()
{
currentSink.definitionList();
}
@Override
public void definitionList( SinkEventAttributes attributes )
{
currentSink.definitionList( attributes );
}
@Override
public void definitionListItem()
{
currentSink.definitionListItem();
}
@Override
public void definitionListItem( SinkEventAttributes attributes )
{
currentSink.definitionListItem( attributes );
}
@Override
public void definitionListItem_()
{
currentSink.definitionListItem_();
}
@Override
public void definitionList_()
{
currentSink.definitionList_();
}
@Override
public void definition_()
{
currentSink.definition_();
}
@Override
public void division()
{
currentSink.division();
}
@Override
public void division( SinkEventAttributes attributes )
{
currentSink.division( attributes );
}
@Override
public void division_()
{
currentSink.division_();
}
@Override
public void figure()
{
currentSink.figure();
}
@Override
public void figure( SinkEventAttributes attributes )
{
currentSink.figure( attributes );
}
@Override
public void figureCaption()
{
currentSink.figureCaption();
}
@Override
public void figureCaption( SinkEventAttributes attributes )
{
currentSink.figureCaption( attributes );
}
@Override
public void figureCaption_()
{
currentSink.figureCaption_();
}
@Override
public void figureGraphics( String name )
{
currentSink.figureGraphics( name );
}
@Override
public void figureGraphics( String src, SinkEventAttributes attributes )
{
currentSink.figureGraphics( src, attributes );
}
@Override
public void figure_()
{
currentSink.figure_();
}
/**
* Flush all sinks
*/
public void flush()
{
for ( int i = 0; i < sinks.size(); i++ )
{
// first flush to get complete buffer
// sink is responsible for flushing it's stream
Sink sink = sinks.get( i );
sink.flush();
ByteArrayOutputStream stream = outputStreams.get( i );
try
{
coreOutputStream.write( stream.toByteArray() );
}
catch ( IOException e )
{
// @todo
}
}
coreSink.flush();
}
@Override
public void footer()
{
currentSink.footer();
}
@Override
public void footer( SinkEventAttributes attributes )
{
currentSink.footer( attributes );
}
@Override
public void footer_()
{
currentSink.footer_();
}
@Override
public void head()
{
currentSink.head();
}
@Override
public void head( SinkEventAttributes attributes )
{
currentSink.head( attributes );
}
@Override
public void head_()
{
currentSink.head_();
}
@Override
public void header()
{
currentSink.header();
}
@Override
public void header( SinkEventAttributes attributes )
{
currentSink.header( attributes );
}
@Override
public void header_()
{
currentSink.header_();
}
@Override
public void horizontalRule()
{
currentSink.horizontalRule();
}
@Override
public void horizontalRule( SinkEventAttributes attributes )
{
currentSink.horizontalRule( attributes );
}
@Override
public void inline()
{
currentSink.inline();
}
@Override
public void inline( SinkEventAttributes attributes )
{
currentSink.inline( attributes );
}
@Override
public void inline_()
{
currentSink.inline_();
}
@Override
public void italic()
{
currentSink.italic();
}
@Override
public void italic_()
{
currentSink.italic_();
}
@Override
public void lineBreak()
{
currentSink.lineBreak();
}
@Override
public void lineBreak( SinkEventAttributes attributes )
{
currentSink.lineBreak( attributes );
}
@Override
public void lineBreakOpportunity()
{
currentSink.lineBreakOpportunity();
}
@Override
public void lineBreakOpportunity( SinkEventAttributes attributes )
{
currentSink.lineBreakOpportunity( attributes );
}
@Override
public void link( String name )
{
currentSink.link( name );
}
@Override
public void link( String name, SinkEventAttributes attributes )
{
currentSink.link( name, attributes );
}
@Override
public void link_()
{
currentSink.link_();
}
@Override
public void list()
{
currentSink.list();
}
@Override
public void list( SinkEventAttributes attributes )
{
currentSink.list( attributes );
}
@Override
public void listItem()
{
currentSink.listItem();
}
@Override
public void listItem( SinkEventAttributes attributes )
{
currentSink.listItem( attributes );
}
@Override
public void listItem_()
{
currentSink.listItem_();
}
@Override
public void list_()
{
currentSink.list_();
}
@Override
public void monospaced()
{
currentSink.monospaced();
}
@Override
public void monospaced_()
{
currentSink.monospaced_();
}
@Override
public void navigation()
{
currentSink.navigation();
}
@Override
public void navigation( SinkEventAttributes attributes )
{
currentSink.navigation( attributes );
}
@Override
public void navigation_()
{
currentSink.navigation_();
}
@Override
public void nonBreakingSpace()
{
currentSink.nonBreakingSpace();
}
@Override
public void numberedList( int numbering )
{
currentSink.numberedList( numbering );
}
@Override
public void numberedList( int numbering, SinkEventAttributes attributes )
{
currentSink.numberedList( numbering, attributes );
}
@Override
public void numberedListItem()
{
currentSink.numberedListItem();
}
@Override
public void numberedListItem( SinkEventAttributes attributes )
{
currentSink.numberedListItem( attributes );
}
@Override
public void numberedListItem_()
{
currentSink.numberedListItem_();
}
@Override
public void numberedList_()
{
currentSink.numberedList_();
}
@Override
public void pageBreak()
{
currentSink.pageBreak();
}
@Override
public void paragraph()
{
currentSink.paragraph();
}
@Override
public void paragraph( SinkEventAttributes attributes )
{
currentSink.paragraph( attributes );
}
@Override
public void paragraph_()
{
currentSink.paragraph_();
}
@Override
public void rawText( String text )
{
currentSink.rawText( text );
}
@Override
public void section( int level, SinkEventAttributes attributes )
{
currentSink.section( level, attributes );
}
@Override
public void section1()
{
currentSink.section1();
}
@Override
public void section1_()
{
currentSink.section1_();
}
@Override
public void section2()
{
currentSink.section2();
}
@Override
public void section2_()
{
currentSink.section2_();
}
@Override
public void section3()
{
currentSink.section3();
}
@Override
public void section3_()
{
currentSink.section3_();
}
@Override
public void section4()
{
currentSink.section4();
}
@Override
public void section4_()
{
currentSink.section4_();
}
@Override
public void section5()
{
currentSink.section5();
}
@Override
public void section5_()
{
currentSink.section5_();
}
@Override
public void section6()
{
currentSink.section5();
}
@Override
public void section6_()
{
currentSink.section5_();
}
@Override
public void sectionTitle()
{
currentSink.sectionTitle();
}
@Override
public void sectionTitle( int level, SinkEventAttributes attributes )
{
currentSink.sectionTitle( level, attributes );
}
@Override
public void sectionTitle1()
{
currentSink.sectionTitle1();
}
@Override
public void sectionTitle1_()
{
currentSink.sectionTitle1_();
}
@Override
public void sectionTitle2()
{
currentSink.sectionTitle2();
}
@Override
public void sectionTitle2_()
{
currentSink.sectionTitle2_();
}
@Override
public void sectionTitle3()
{
currentSink.sectionTitle3();
}
@Override
public void sectionTitle3_()
{
currentSink.sectionTitle3_();
}
@Override
public void sectionTitle4()
{
currentSink.sectionTitle4();
}
@Override
public void sectionTitle4_()
{
currentSink.sectionTitle4_();
}
@Override
public void sectionTitle5()
{
currentSink.sectionTitle5();
}
@Override
public void sectionTitle5_()
{
currentSink.sectionTitle5_();
}
@Override
public void sectionTitle6()
{
currentSink.sectionTitle5();
}
@Override
public void sectionTitle6_()
{
currentSink.sectionTitle5_();
}
@Override
public void sectionTitle_()
{
currentSink.sectionTitle_();
}
@Override
public void sectionTitle_( int level )
{
currentSink.sectionTitle_( level );
}
@Override
public void section_( int level )
{
currentSink.section_( level );
}
@Override
public void sidebar()
{
currentSink.sidebar();
}
@Override
public void sidebar( SinkEventAttributes attributes )
{
currentSink.sidebar( attributes );
}
@Override
public void sidebar_()
{
currentSink.sidebar_();
}
@Override
public void table()
{
currentSink.table();
}
@Override
public void table( SinkEventAttributes attributes )
{
currentSink.table( attributes );
}
@Override
public void tableCaption()
{
currentSink.tableCaption();
}
@Override
public void tableCaption( SinkEventAttributes attributes )
{
currentSink.tableCaption( attributes );
}
@Override
public void tableCaption_()
{
currentSink.tableCaption_();
}
@Override
public void tableCell()
{
currentSink.tableCell();
}
@Override
public void tableCell( String width )
{
currentSink.tableCell( width );
}
@Override
public void tableCell( SinkEventAttributes attributes )
{
currentSink.tableCell( attributes );
}
@Override
public void tableCell_()
{
currentSink.tableCell_();
}
@Override
public void tableHeaderCell()
{
currentSink.tableHeaderCell();
}
@Override
public void tableHeaderCell( String width )
{
currentSink.tableHeaderCell( width );
}
@Override
public void tableHeaderCell( SinkEventAttributes attributes )
{
currentSink.tableHeaderCell( attributes );
}
@Override
public void tableHeaderCell_()
{
currentSink.tableHeaderCell_();
}
@Override
public void tableRow()
{
currentSink.tableRow();
}
@Override
public void tableRow( SinkEventAttributes attributes )
{
currentSink.tableRow( attributes );
}
@Override
public void tableRow_()
{
currentSink.tableRow_();
}
@Override
public void tableRows( int[] justification, boolean grid )
{
currentSink.tableRows( justification, grid );
}
@Override
public void tableRows_()
{
currentSink.tableRows_();
}
@Override
public void table_()
{
currentSink.table_();
}
@Override
public void text( String text )
{
currentSink.text( text );
}
@Override
public void text( String text, SinkEventAttributes attributes )
{
currentSink.text( text, attributes );
}
@Override
public void time( String datetime )
{
currentSink.time( datetime );
}
@Override
public void time( String datetime, SinkEventAttributes attributes )
{
currentSink.time( datetime, attributes );
}
@Override
public void time_()
{
currentSink.time_();
}
@Override
public void title()
{
currentSink.title();
}
@Override
public void title( SinkEventAttributes attributes )
{
currentSink.title( attributes );
}
@Override
public void title_()
{
currentSink.title_();
}
@Override
public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes )
{
currentSink.unknown( name, requiredParams, attributes );
}
@Override
public void verbatim( boolean boxed )
{
currentSink.verbatim( boxed );
}
@Override
public void verbatim( SinkEventAttributes attributes )
{
currentSink.verbatim( attributes );
}
@Override
public void verbatim_()
{
currentSink.verbatim_();
}
@Override
public void enableLogging( Log log )
{
currentSink.enableLogging( log );
}
}