You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2012/01/07 14:50:47 UTC
svn commit: r1228615 - in /maven/doxia/doxia/trunk/doxia-core/src:
main/java/org/apache/maven/doxia/sink/RandomAccessSink.java
site/apt/using-randomaccesssink.apt site/site.xml
test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java
Author: rfscholte
Date: Sat Jan 7 13:50:47 2012
New Revision: 1228615
URL: http://svn.apache.org/viewvc?rev=1228615&view=rev
Log:
Fix DOXIA-387: Add RandomAccessSink
Added:
maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/RandomAccessSink.java
maven/doxia/doxia/trunk/doxia-core/src/site/apt/using-randomaccesssink.apt
maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java
Modified:
maven/doxia/doxia/trunk/doxia-core/src/site/site.xml
Added: maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/RandomAccessSink.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/RandomAccessSink.java?rev=1228615&view=auto
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/RandomAccessSink.java (added)
+++ maven/doxia/doxia/trunk/doxia-core/src/main/java/org/apache/maven/doxia/sink/RandomAccessSink.java Sat Jan 7 13:50:47 2012
@@ -0,0 +1,898 @@
+package org.apache.maven.doxia.sink;
+
+/*
+ * 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;
+
+/**
+ * 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<Sink>();
+
+ private List<ByteArrayOutputStream> outputStreams = new ArrayList<ByteArrayOutputStream>();
+
+ private Sink currentSink;
+
+ public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream )
+ throws IOException
+ {
+ this.sinkFactory = sinkFactory;
+ this.coreOutputStream = stream;
+ this.coreSink = this.currentSink = sinkFactory.createSink( stream );
+ }
+
+ public RandomAccessSink( SinkFactory sinkFactory, OutputStream stream, String encoding )
+ throws IOException
+ {
+ this.sinkFactory = sinkFactory;
+ this.coreOutputStream = stream;
+ this.encoding = encoding;
+ this.coreSink = this.currentSink = sinkFactory.createSink( stream, encoding );
+ }
+
+ public RandomAccessSink( SinkFactory sinkFactory, File outputDirectory, String outputName )
+ throws IOException
+ {
+ this.sinkFactory = sinkFactory;
+ this.coreOutputStream = new FileOutputStream( new File( outputDirectory, outputName ) );
+ this.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream );
+ }
+
+ 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.coreSink = this.currentSink = sinkFactory.createSink( coreOutputStream, encoding );
+ }
+
+ /**
+ * 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;
+ }
+
+ /** {@inheritDoc} */
+ public void anchor( String name )
+ {
+ currentSink.anchor( name );
+ }
+
+ /** {@inheritDoc} */
+ public void anchor( String name, SinkEventAttributes attributes )
+ {
+ currentSink.anchor( name, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void anchor_()
+ {
+ currentSink.anchor_();
+ }
+
+ /** {@inheritDoc} */
+ public void author()
+ {
+ currentSink.author();
+ }
+
+ /** {@inheritDoc} */
+ public void author( SinkEventAttributes attributes )
+ {
+ currentSink.author( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void author_()
+ {
+ currentSink.author_();
+ }
+
+ /** {@inheritDoc} */
+ public void body()
+ {
+ currentSink.body();
+ }
+
+ /** {@inheritDoc} */
+ public void body( SinkEventAttributes attributes )
+ {
+ currentSink.body( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void body_()
+ {
+ currentSink.body_();
+ }
+
+ /** {@inheritDoc} */
+ public void bold()
+ {
+ currentSink.bold();
+ }
+
+ /** {@inheritDoc} */
+ 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();
+ }
+
+ /** {@inheritDoc} */
+ public void comment( String comment )
+ {
+ currentSink.comment( comment );
+ }
+
+ /** {@inheritDoc} */
+ public void date()
+ {
+ currentSink.date();
+ }
+
+ /** {@inheritDoc} */
+ public void date( SinkEventAttributes attributes )
+ {
+ currentSink.date( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void date_()
+ {
+ currentSink.date_();
+ }
+
+ /** {@inheritDoc} */
+ public void definedTerm()
+ {
+ currentSink.definedTerm();
+ }
+
+ /** {@inheritDoc} */
+ public void definedTerm( SinkEventAttributes attributes )
+ {
+ currentSink.definedTerm( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void definedTerm_()
+ {
+ currentSink.definedTerm_();
+ }
+
+ /** {@inheritDoc} */
+ public void definition()
+ {
+ currentSink.definition();
+ }
+
+ /** {@inheritDoc} */
+ public void definition( SinkEventAttributes attributes )
+ {
+ currentSink.definition( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void definitionList()
+ {
+ currentSink.definitionList();
+ }
+
+ /** {@inheritDoc} */
+ public void definitionList( SinkEventAttributes attributes )
+ {
+ currentSink.definitionList( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void definitionListItem()
+ {
+ currentSink.definitionListItem();
+ }
+
+ /** {@inheritDoc} */
+ public void definitionListItem( SinkEventAttributes attributes )
+ {
+ currentSink.definitionListItem( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void definitionListItem_()
+ {
+ currentSink.definitionListItem_();
+ }
+
+ /** {@inheritDoc} */
+ public void definitionList_()
+ {
+ currentSink.definitionList_();
+ }
+
+ /** {@inheritDoc} */
+ public void definition_()
+ {
+ currentSink.definition_();
+ }
+
+ /** {@inheritDoc} */
+ public void figure()
+ {
+ currentSink.figure();
+ }
+
+ /** {@inheritDoc} */
+ public void figure( SinkEventAttributes attributes )
+ {
+ currentSink.figure( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void figureCaption()
+ {
+ currentSink.figureCaption();
+ }
+
+ /** {@inheritDoc} */
+ public void figureCaption( SinkEventAttributes attributes )
+ {
+ currentSink.figureCaption( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void figureCaption_()
+ {
+ currentSink.figureCaption_();
+ }
+
+ /** {@inheritDoc} */
+ public void figureGraphics( String name )
+ {
+ currentSink.figureGraphics( name );
+ }
+
+ /** {@inheritDoc} */
+ public void figureGraphics( String src, SinkEventAttributes attributes )
+ {
+ currentSink.figureGraphics( src, attributes );
+ }
+
+ /** {@inheritDoc} */
+ 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();
+ }
+
+ /** {@inheritDoc} */
+ public void head()
+ {
+ currentSink.head();
+ }
+
+ /** {@inheritDoc} */
+ public void head( SinkEventAttributes attributes )
+ {
+ currentSink.head( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void head_()
+ {
+ currentSink.head_();
+ }
+
+ /** {@inheritDoc} */
+ public void horizontalRule()
+ {
+ currentSink.horizontalRule();
+ }
+
+ /** {@inheritDoc} */
+ public void horizontalRule( SinkEventAttributes attributes )
+ {
+ currentSink.horizontalRule( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void italic()
+ {
+ currentSink.italic();
+ }
+
+ /** {@inheritDoc} */
+ public void italic_()
+ {
+ currentSink.italic_();
+ }
+
+ /** {@inheritDoc} */
+ public void lineBreak()
+ {
+ currentSink.lineBreak();
+ }
+
+ /** {@inheritDoc} */
+ public void lineBreak( SinkEventAttributes attributes )
+ {
+ currentSink.lineBreak( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void link( String name )
+ {
+ currentSink.link( name );
+ }
+
+ /** {@inheritDoc} */
+ public void link( String name, SinkEventAttributes attributes )
+ {
+ currentSink.link( name, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void link_()
+ {
+ currentSink.link_();
+ }
+
+ /** {@inheritDoc} */
+ public void list()
+ {
+ currentSink.list();
+ }
+
+ /** {@inheritDoc} */
+ public void list( SinkEventAttributes attributes )
+ {
+ currentSink.list( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void listItem()
+ {
+ currentSink.listItem();
+ }
+
+ /** {@inheritDoc} */
+ public void listItem( SinkEventAttributes attributes )
+ {
+ currentSink.listItem( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void listItem_()
+ {
+ currentSink.listItem_();
+ }
+
+ /** {@inheritDoc} */
+ public void list_()
+ {
+ currentSink.list_();
+ }
+
+ /** {@inheritDoc} */
+ public void monospaced()
+ {
+ currentSink.monospaced();
+ }
+
+ /** {@inheritDoc} */
+ public void monospaced_()
+ {
+ currentSink.monospaced_();
+ }
+
+ /** {@inheritDoc} */
+ public void nonBreakingSpace()
+ {
+ currentSink.nonBreakingSpace();
+ }
+
+ /** {@inheritDoc} */
+ public void numberedList( int numbering )
+ {
+ currentSink.numberedList( numbering );
+ }
+
+ /** {@inheritDoc} */
+ public void numberedList( int numbering, SinkEventAttributes attributes )
+ {
+ currentSink.numberedList( numbering, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void numberedListItem()
+ {
+ currentSink.numberedListItem();
+ }
+
+ /** {@inheritDoc} */
+ public void numberedListItem( SinkEventAttributes attributes )
+ {
+ currentSink.numberedListItem( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void numberedListItem_()
+ {
+ currentSink.numberedListItem_();
+ }
+
+ /** {@inheritDoc} */
+ public void numberedList_()
+ {
+ currentSink.numberedList_();
+ }
+
+ /** {@inheritDoc} */
+ public void pageBreak()
+ {
+ currentSink.pageBreak();
+ }
+
+ /** {@inheritDoc} */
+ public void paragraph()
+ {
+ currentSink.paragraph();
+ }
+
+ /** {@inheritDoc} */
+ public void paragraph( SinkEventAttributes attributes )
+ {
+ currentSink.paragraph( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void paragraph_()
+ {
+ currentSink.paragraph_();
+ }
+
+ /** {@inheritDoc} */
+ public void rawText( String text )
+ {
+ currentSink.rawText( text );
+ }
+
+ /** {@inheritDoc} */
+ public void section( int level, SinkEventAttributes attributes )
+ {
+ currentSink.section( level, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void section1()
+ {
+ currentSink.section1();
+ }
+
+ /** {@inheritDoc} */
+ public void section1_()
+ {
+ currentSink.section1_();
+ }
+
+ /** {@inheritDoc} */
+ public void section2()
+ {
+ currentSink.section2();
+ }
+
+ /** {@inheritDoc} */
+ public void section2_()
+ {
+ currentSink.section2_();
+ }
+
+ /** {@inheritDoc} */
+ public void section3()
+ {
+ currentSink.section3();
+ }
+
+ /** {@inheritDoc} */
+ public void section3_()
+ {
+ currentSink.section3_();
+ }
+
+ /** {@inheritDoc} */
+ public void section4()
+ {
+ currentSink.section4();
+ }
+
+ /** {@inheritDoc} */
+ public void section4_()
+ {
+ currentSink.section4_();
+ }
+
+ /** {@inheritDoc} */
+ public void section5()
+ {
+ currentSink.section5();
+ }
+
+ /** {@inheritDoc} */
+ public void section5_()
+ {
+ currentSink.section5_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle()
+ {
+ currentSink.sectionTitle();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle( int level, SinkEventAttributes attributes )
+ {
+ currentSink.sectionTitle( level, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle1()
+ {
+ currentSink.sectionTitle1();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle1_()
+ {
+ currentSink.sectionTitle1_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle2()
+ {
+ currentSink.sectionTitle2();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle2_()
+ {
+ currentSink.sectionTitle2_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle3()
+ {
+ currentSink.sectionTitle3();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle3_()
+ {
+ currentSink.sectionTitle3_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle4()
+ {
+ currentSink.sectionTitle4();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle4_()
+ {
+ currentSink.sectionTitle4_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle5()
+ {
+ currentSink.sectionTitle5();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle5_()
+ {
+ currentSink.sectionTitle5_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle_()
+ {
+ currentSink.sectionTitle_();
+ }
+
+ /** {@inheritDoc} */
+ public void sectionTitle_( int level )
+ {
+ currentSink.sectionTitle_( level );
+ }
+
+ /** {@inheritDoc} */
+ public void section_( int level )
+ {
+ currentSink.section_( level );
+ }
+
+ /** {@inheritDoc} */
+ public void table()
+ {
+ currentSink.table();
+ }
+
+ /** {@inheritDoc} */
+ public void table( SinkEventAttributes attributes )
+ {
+ currentSink.table( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void tableCaption()
+ {
+ currentSink.tableCaption();
+ }
+
+ /** {@inheritDoc} */
+ public void tableCaption( SinkEventAttributes attributes )
+ {
+ currentSink.tableCaption( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void tableCaption_()
+ {
+ currentSink.tableCaption_();
+ }
+
+ /** {@inheritDoc} */
+ public void tableCell()
+ {
+ currentSink.tableCell();
+ }
+
+ /** {@inheritDoc} */
+ public void tableCell( String width )
+ {
+ currentSink.tableCell( width );
+ }
+
+ /** {@inheritDoc} */
+ public void tableCell( SinkEventAttributes attributes )
+ {
+ currentSink.tableCell( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void tableCell_()
+ {
+ currentSink.tableCell_();
+ }
+
+ /** {@inheritDoc} */
+ public void tableHeaderCell()
+ {
+ currentSink.tableHeaderCell();
+ }
+
+ /** {@inheritDoc} */
+ public void tableHeaderCell( String width )
+ {
+ currentSink.tableHeaderCell( width );
+ }
+
+ /** {@inheritDoc} */
+ public void tableHeaderCell( SinkEventAttributes attributes )
+ {
+ currentSink.tableHeaderCell( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void tableHeaderCell_()
+ {
+ currentSink.tableHeaderCell_();
+ }
+
+ /** {@inheritDoc} */
+ public void tableRow()
+ {
+ currentSink.tableRow();
+ }
+
+ /** {@inheritDoc} */
+ public void tableRow( SinkEventAttributes attributes )
+ {
+ currentSink.tableRow( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void tableRow_()
+ {
+ currentSink.tableRow_();
+ }
+
+ /** {@inheritDoc} */
+ public void tableRows( int[] justification, boolean grid )
+ {
+ currentSink.tableRows( justification, grid );
+ }
+
+ /** {@inheritDoc} */
+ public void tableRows_()
+ {
+ currentSink.tableRows_();
+ }
+
+ /** {@inheritDoc} */
+ public void table_()
+ {
+ currentSink.table_();
+ }
+
+ /** {@inheritDoc} */
+ public void text( String text )
+ {
+ currentSink.text( text );
+ }
+
+ /** {@inheritDoc} */
+ public void text( String text, SinkEventAttributes attributes )
+ {
+ currentSink.text( text, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void title()
+ {
+ currentSink.title();
+ }
+
+ /** {@inheritDoc} */
+ public void title( SinkEventAttributes attributes )
+ {
+ currentSink.title( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void title_()
+ {
+ currentSink.title_();
+ }
+
+ /** {@inheritDoc} */
+ public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes )
+ {
+ currentSink.unknown( name, requiredParams, attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void verbatim( boolean boxed )
+ {
+ currentSink.verbatim( boxed );
+ }
+
+ /** {@inheritDoc} */
+ public void verbatim( SinkEventAttributes attributes )
+ {
+ currentSink.verbatim( attributes );
+ }
+
+ /** {@inheritDoc} */
+ public void verbatim_()
+ {
+ currentSink.verbatim_();
+ }
+
+ /** {@inheritDoc} */
+ public void enableLogging( Log log )
+ {
+ currentSink.enableLogging( log );
+ }
+}
\ No newline at end of file
Added: maven/doxia/doxia/trunk/doxia-core/src/site/apt/using-randomaccesssink.apt
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/site/apt/using-randomaccesssink.apt?rev=1228615&view=auto
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/site/apt/using-randomaccesssink.apt (added)
+++ maven/doxia/doxia/trunk/doxia-core/src/site/apt/using-randomaccesssink.apt Sat Jan 7 13:50:47 2012
@@ -0,0 +1,70 @@
+ -----
+ Using RandomAccessSink
+ -----
+ Robert Scholte
+ ------
+ 2011-01-07
+ ------
+
+~~ 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.
+
+~~ NOTE: For help with the syntax of this file, see:
+~~ http://maven.apache.org/doxia/references/apt-format.html
+
+Using the RandomAccessSink
+
+ The RandomAccessSink is a Sink with the ability to add hooks.
+ To demonstrate its usage we can have a look at a FML (FAQ Markup Language)-page.
+ The simple structure of such a page can be like:
+
++----------------+
+ <faq id="1">
+ <question/>
+ <answer/>
+ </faq>
+ <faq id="2">
+ <question/>
+ <answer/>
+ </faq>
++----------------+
+
+ Such structure would be parsed to the following page:
+
+*-------------------------------+
+| faq\["1"\].question \+ link \
+| faq\["2"\].question \+ link \
+*-------------------------------+
+| faq\["1"\].question \+ anchor \
+| faq\["1"\].answer \
+| faq\["2"\].question \+ anchor \
+| faq\["2"\].answer \
+*-------------------------------+
+
+ With a Sink you can only append and there's no option to buffer.
+ This would mean that you have to go twice over the structure: once for only the questions and once for the question + answer.
+
+ When using the RandomAccesSink we can prepare the structure of the page
+
++--------------------------------------------------------------------------------------------------*
+ RandomAccessSink randomAccessSink = new RandomAccessSink( sinkFactory, outputStream, encoding );
+ Sink questions = randomAccessSink.addSinkHook();
+ Sink qAndA = randomAccessSink.addSinkHook();
++--------------------------------------------------------------------------------------------------*
+
+ Now you can append the first question to both sinks, and append the answer to the second one.
+ The same can be done with the second faq-entry.
Modified: maven/doxia/doxia/trunk/doxia-core/src/site/site.xml
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/site/site.xml?rev=1228615&r1=1228614&r2=1228615&view=diff
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/site/site.xml (original)
+++ maven/doxia/doxia/trunk/doxia-core/src/site/site.xml Sat Jan 7 13:50:47 2012
@@ -38,6 +38,7 @@
<menu name="Document Schema">
<item name="Reference" href="document.html"/>
<item name="Using Document Schema" href="using-document-xsd.html"/>
+ <item name="Using RandomAccessSink" href="using-randomaccesssink.html"/>
</menu>
<menu ref="reports"/>
Added: maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java
URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java?rev=1228615&view=auto
==============================================================================
--- maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java (added)
+++ maven/doxia/doxia/trunk/doxia-core/src/test/java/org/apache/maven/doxia/sink/RandomAccessSinkTest.java Sat Jan 7 13:50:47 2012
@@ -0,0 +1,104 @@
+package org.apache.maven.doxia.sink;
+
+/*
+ * 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.
+ */
+
+/**
+ * @author Robert Scholte
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.Writer;
+
+import junit.framework.TestCase;
+
+public class RandomAccessSinkTest
+ extends TestCase
+{
+ private SinkFactory factory = new AbstractXmlSinkFactory()
+ {
+
+ protected Sink createSink( Writer writer, String encoding, String languageId )
+ {
+ return new TextSink( writer );
+ }
+
+ protected Sink createSink( Writer writer, String encoding )
+ {
+ return new TextSink( writer );
+ }
+ };
+
+ private void buildSimple( Sink sink, String text )
+ throws Exception
+ {
+ sink.anchor( "foobar" );
+ sink.text( text );
+ sink.anchor_();
+ }
+
+ public void testSimple()
+ throws Exception
+ {
+ String encoding = "UTF-8";
+ String text = "Hello World";
+ ByteArrayOutputStream outFlatSink = new ByteArrayOutputStream();
+ Sink flatSink = factory.createSink( outFlatSink, encoding );
+ buildSimple( flatSink, text );
+ flatSink.flush();
+ flatSink.close();
+
+ ByteArrayOutputStream outRandomAccessSink = new ByteArrayOutputStream();
+ RandomAccessSink randomAccessSink = new RandomAccessSink( factory, outRandomAccessSink, encoding );
+ buildSimple( randomAccessSink, text );
+ randomAccessSink.flush();
+ randomAccessSink.close();
+
+ assertEquals( outFlatSink.toString( encoding ), outRandomAccessSink.toString( encoding ) );
+ }
+
+ public void testComplex()
+ throws Exception
+ {
+ String encoding = "UTF-8";
+ String summaryText = "Summary text";
+ String detailText = "Detail text";
+ ByteArrayOutputStream outFlatSink = new ByteArrayOutputStream();
+ Sink flatSink = factory.createSink( outFlatSink, encoding );
+ buildSimple( flatSink, summaryText );
+ flatSink.horizontalRule();
+ buildSimple( flatSink, detailText );
+ flatSink.flush();
+ flatSink.close();
+
+ ByteArrayOutputStream outRandomAccessSink = new ByteArrayOutputStream();
+ RandomAccessSink randomAccessSink = new RandomAccessSink( factory, outRandomAccessSink, encoding );
+ Sink summarySink = randomAccessSink.addSinkHook();
+ randomAccessSink.horizontalRule();
+ Sink detailSink = randomAccessSink.addSinkHook();
+
+ // here's an example of the strength of randomAccessSink. Summary and detail are built in reverse order
+ buildSimple( detailSink, detailText );
+ buildSimple( summarySink, summaryText );
+
+ randomAccessSink.flush();
+ randomAccessSink.close();
+
+ assertEquals( outFlatSink.toString( encoding ), outRandomAccessSink.toString( encoding ) );
+ }
+}
\ No newline at end of file