This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-doxia.git
The following commit(s) were added to refs/heads/master by this push:
new 1fef4c57 [DOXIA-711] Introduce SinkWrapper and according
SinkWrapperFactory (#184)
1fef4c57 is described below
commit 1fef4c578dc3d1f868893e8ea8afc60d4cc6a0c8
Author: Konrad Windszus <[email protected]>
AuthorDate: Sun Dec 24 10:48:42 2023 +0100
[DOXIA-711] Introduce SinkWrapper and according SinkWrapperFactory (#184)
Add a BufferingSinkProxyWrapper which buffers all calls on the
underlying sink until it is flushed.
Deprecate PipelineSink and RandomAccessSink to reference the
more effective SinkWrapper approach.
---
.../apache/maven/doxia/parser/AbstractParser.java | 46 +-
.../maven/doxia/parser/AbstractXmlParser.java | 2 +-
.../java/org/apache/maven/doxia/parser/Parser.java | 16 +
.../doxia/sink/impl/BufferingSinkProxyFactory.java | 112 +++
.../apache/maven/doxia/sink/impl/PipelineSink.java | 3 +
.../maven/doxia/sink/impl/RandomAccessSink.java | 969 +--------------------
.../apache/maven/doxia/sink/impl/SinkWrapper.java | 529 +++++++++++
.../maven/doxia/sink/impl/SinkWrapperFactory.java | 43 +
.../sink/impl/SinkWrapperFactoryComparator.java | 33 +
.../maven/doxia/parser/AbstractParserTest.java | 63 +-
.../apache/maven/doxia/module/apt/AptParser.java | 2 +-
.../apache/maven/doxia/module/fml/FmlParser.java | 2 +-
.../doxia/module/markdown/MarkdownParser.java | 2 +-
13 files changed, 859 insertions(+), 963 deletions(-)
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractParser.java
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractParser.java
index 1e868135..a55f1aa1 100644
--- a/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractParser.java
+++ b/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractParser.java
@@ -25,6 +25,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.PriorityQueue;
import java.util.Properties;
import org.apache.maven.doxia.macro.Macro;
@@ -33,6 +36,8 @@ import org.apache.maven.doxia.macro.MacroRequest;
import org.apache.maven.doxia.macro.manager.MacroManager;
import org.apache.maven.doxia.macro.manager.MacroNotFoundException;
import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.doxia.sink.impl.SinkWrapperFactory;
+import org.apache.maven.doxia.sink.impl.SinkWrapperFactoryComparator;
/**
* An abstract base class that defines some convenience methods for parsers.
@@ -48,6 +53,11 @@ public abstract class AbstractParser implements Parser {
@Inject
private MacroManager macroManager;
+ @Inject
+ private Collection<SinkWrapperFactory>
automaticallyRegisteredSinkWrapperFactories;
+
+ private final Collection<SinkWrapperFactory>
manuallyRegisteredSinkWrapperFactories = new LinkedList<>();
+
/**
* Emit Doxia comment events when parsing comments?
*/
@@ -171,7 +181,25 @@ public abstract class AbstractParser implements Parser {
}
/**
- * Set <code>secondParsing</code> to true, if we need a second parsing.
+ * Retrieves the sink pipeline built from all registered {@link
SinkWrapperFactory} objects.
+ * For secondary parsers (i.e. ones with {@link #isSecondParsing()}
returning {@code true} just the given original sink is returned.
+ * @param sink
+ * @return the Sink pipeline to be used
+ */
+ protected Sink getWrappedSink(Sink sink) {
+ // no wrapping for secondary parsing
+ if (secondParsing) {
+ return sink;
+ }
+ Sink currentSink = sink;
+ for (SinkWrapperFactory factory : getSinkWrapperFactories()) {
+ currentSink = factory.createWrapper(currentSink);
+ }
+ return currentSink;
+ }
+
+ /**
+ * Set <code>secondParsing</code> to true, if this represents a secondary
parsing of the same source.
*
* @param second true for second parsing
*/
@@ -189,6 +217,22 @@ public abstract class AbstractParser implements Parser {
return secondParsing;
}
+ @Override
+ public void addSinkWrapperFactory(SinkWrapperFactory factory) {
+ manuallyRegisteredSinkWrapperFactories.add(factory);
+ }
+
+ @Override
+ public Collection<SinkWrapperFactory> getSinkWrapperFactories() {
+ PriorityQueue<SinkWrapperFactory> effectiveSinkWrapperFactories =
+ new PriorityQueue<>(new SinkWrapperFactoryComparator());
+ if (automaticallyRegisteredSinkWrapperFactories != null) {
+
effectiveSinkWrapperFactories.addAll(automaticallyRegisteredSinkWrapperFactories);
+ }
+
effectiveSinkWrapperFactories.addAll(manuallyRegisteredSinkWrapperFactories);
+ return effectiveSinkWrapperFactories;
+ }
+
/**
* Gets the current {@link MacroManager}.
*
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractXmlParser.java
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractXmlParser.java
index b4cbbfaa..d0d143d6 100644
---
a/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractXmlParser.java
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/AbstractXmlParser.java
@@ -131,7 +131,7 @@ public abstract class AbstractXmlParser extends
AbstractParser implements XmlMar
// Note: do it after input is set, otherwise values are reset
initXmlParser(parser);
- parseXml(parser, sink);
+ parseXml(parser, getWrappedSink(sink));
} catch (XmlPullParserException ex) {
throw new ParseException("Error parsing the model", ex,
ex.getLineNumber(), ex.getColumnNumber());
} catch (MacroExecutionException ex) {
diff --git a/doxia-core/src/main/java/org/apache/maven/doxia/parser/Parser.java
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/Parser.java
index e09953ed..da165895 100644
--- a/doxia-core/src/main/java/org/apache/maven/doxia/parser/Parser.java
+++ b/doxia-core/src/main/java/org/apache/maven/doxia/parser/Parser.java
@@ -19,8 +19,10 @@
package org.apache.maven.doxia.parser;
import java.io.Reader;
+import java.util.Collection;
import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.doxia.sink.impl.SinkWrapperFactory;
/**
* A Parser is responsible for parsing any document in a supported front-end
@@ -83,4 +85,18 @@ public interface Parser {
* @return <code>true</code> (default value) if comment Doxia events are
emitted
*/
boolean isEmitComments();
+
+ /**
+ * Registers a given {@link SinkWrapperFactory} with the parser used in
subsequent calls of {@code parse(...)}
+ * @param factory the factory to create the sink wrapper
+ * @since 2.0.0
+ */
+ void addSinkWrapperFactory(SinkWrapperFactory factory);
+
+ /**
+ *
+ * @return all sink wrapper factories in the correct order (both
registered automatically and manually)
+ * @since 2.0.0
+ */
+ Collection<SinkWrapperFactory> getSinkWrapperFactories();
}
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/BufferingSinkProxyFactory.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/BufferingSinkProxyFactory.java
new file mode 100644
index 00000000..17fb1f0e
--- /dev/null
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/BufferingSinkProxyFactory.java
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+package org.apache.maven.doxia.sink.impl;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import org.apache.maven.doxia.sink.Sink;
+
+/**
+ * Buffers all method calls on the proxied Sink until its {@link Sink#flush()}
is called.
+ */
+public class BufferingSinkProxyFactory implements SinkWrapperFactory {
+
+ private static final class MethodWithArguments {
+ private final Method method;
+ private final Object[] args;
+
+ MethodWithArguments(Method method, Object[] args) {
+ super();
+ this.method = method;
+ this.args = args;
+ }
+
+ void invoke(Object object) {
+ try {
+ method.invoke(object, args);
+ } catch (IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
+ throw new IllegalStateException("Could not call buffered
method " + method, e);
+ }
+ }
+ }
+
+ public interface BufferingSink extends Sink {
+ // just a marker interface
+ Sink getBufferedSink();
+ }
+
+ private static final class BufferingSinkProxy implements InvocationHandler
{
+ private final Queue<MethodWithArguments> bufferedInvocations;
+ private final Sink delegate;
+ private static final Method FLUSH_METHOD;
+ private static final Method GET_BUFFERED_SINK_METHOD;
+
+ static {
+ try {
+ FLUSH_METHOD = Sink.class.getMethod("flush");
+ GET_BUFFERED_SINK_METHOD =
BufferingSink.class.getMethod("getBufferedSink");
+ } catch (NoSuchMethodException | SecurityException e) {
+ throw new IllegalStateException("Could not find flush method
in Sink!", e);
+ }
+ }
+
+ BufferingSinkProxy(Sink delegate) {
+ bufferedInvocations = new LinkedList<>();
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
+ if (method.equals(FLUSH_METHOD)) {
+ bufferedInvocations.forEach(i -> i.invoke(delegate));
+ bufferedInvocations.clear();
+ } else if (method.equals(GET_BUFFERED_SINK_METHOD)) {
+ return delegate;
+ } else {
+ bufferedInvocations.add(new MethodWithArguments(method, args));
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public Sink createWrapper(Sink delegate) {
+ BufferingSinkProxy proxy = new BufferingSinkProxy(delegate);
+ return (Sink) Proxy.newProxyInstance(
+ delegate.getClass().getClassLoader(), new Class<?>[]
{BufferingSink.class}, proxy);
+ }
+
+ public static BufferingSink castAsBufferingSink(Sink sink) {
+ if (sink instanceof BufferingSink) {
+ return (BufferingSink) sink;
+ } else {
+ throw new IllegalArgumentException("The given sink is not a
BufferingSink but a " + sink.getClass());
+ }
+ }
+
+ @Override
+ public int getPriority() {
+ return 0;
+ }
+}
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/PipelineSink.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/PipelineSink.java
index a670eb5f..b9a1bf7e 100644
---
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/PipelineSink.java
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/PipelineSink.java
@@ -28,9 +28,12 @@ import org.apache.maven.doxia.sink.Sink;
/**
* May be used to invoke the same method on a List of Sinks.
+ * @deprecated Use the {@link SinkWrapper} approach which doesn't require the
use of dynamic proxies.
*
* @author <a href="mailto:[email protected]">Trygve Laugstøl</a>
+ * @see SinkWrapper
*/
+@Deprecated
public class PipelineSink implements InvocationHandler {
private List<Sink> pipeline;
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/RandomAccessSink.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/RandomAccessSink.java
index f35d030a..33993714 100644
---
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/RandomAccessSink.java
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/RandomAccessSink.java
@@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.maven.doxia.sink.Sink;
-import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.sink.SinkFactory;
/**
@@ -35,11 +34,16 @@ import org.apache.maven.doxia.sink.SinkFactory;
* 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.
+ * @deprecated Use {@link BufferingSinkProxyFactory} instead which buffers on
the (higher) Sink API level
+ * which usually is less memory intense than buffering the output stream which
is done by this class.
+ * Also it doesn't require dynamically creating new sinks leveraging a {@link
SinkFactory}.
*
* @author Robert Scholte
* @since 1.3
+ * @see BufferingSinkProxyFactory
*/
-public class RandomAccessSink implements Sink {
+@Deprecated
+public class RandomAccessSink extends SinkWrapper {
private SinkFactory sinkFactory;
private String encoding;
@@ -62,10 +66,10 @@ public class RandomAccessSink implements Sink {
* @throws java.io.IOException if any.
*/
public RandomAccessSink(SinkFactory sinkFactory, OutputStream stream)
throws IOException {
+ super(sinkFactory.createSink(stream));
this.sinkFactory = sinkFactory;
this.coreOutputStream = stream;
- this.currentSink = sinkFactory.createSink(stream);
- this.coreSink = this.currentSink;
+ this.coreSink = getWrappedSink();
}
/**
@@ -77,11 +81,11 @@ public class RandomAccessSink implements Sink {
* @throws java.io.IOException if any.
*/
public RandomAccessSink(SinkFactory sinkFactory, OutputStream stream,
String encoding) throws IOException {
+ super(sinkFactory.createSink(stream, encoding));
this.sinkFactory = sinkFactory;
this.coreOutputStream = stream;
this.encoding = encoding;
- this.currentSink = sinkFactory.createSink(stream, encoding);
- this.coreSink = this.currentSink;
+ this.coreSink = getWrappedSink();
}
/**
@@ -93,10 +97,12 @@ public class RandomAccessSink implements Sink {
* @throws java.io.IOException if any.
*/
public RandomAccessSink(SinkFactory sinkFactory, File outputDirectory,
String outputName) throws IOException {
+ super(null);
this.sinkFactory = sinkFactory;
this.coreOutputStream = new FileOutputStream(new File(outputDirectory,
outputName));
this.currentSink = sinkFactory.createSink(coreOutputStream);
this.coreSink = this.currentSink;
+ setWrappedSink(currentSink);
}
/**
@@ -110,29 +116,13 @@ public class RandomAccessSink implements Sink {
*/
public RandomAccessSink(SinkFactory sinkFactory, File outputDirectory,
String outputName, String encoding)
throws IOException {
+ super(null);
this.sinkFactory = sinkFactory;
this.coreOutputStream = new FileOutputStream(new File(outputDirectory,
outputName));
this.encoding = encoding;
this.currentSink = sinkFactory.createSink(coreOutputStream, encoding);
this.coreSink = this.currentSink;
- }
-
- /** {@inheritDoc} */
- @Override
- public void address() {
- currentSink.address();
- }
-
- /** {@inheritDoc} */
- @Override
- public void address(SinkEventAttributes attributes) {
- currentSink.address(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void address_() {
- currentSink.address_();
+ setWrappedSink(currentSink);
}
/**
@@ -159,114 +149,13 @@ public class RandomAccessSink implements Sink {
}
sinks.add(subSink);
sinks.add(currentSink);
+ setWrappedSink(currentSink);
} catch (IOException e) {
// IOException can only be caused by our own ByteArrayOutputStream
}
return subSink;
}
- /** {@inheritDoc} */
- @Override
- public void anchor(String name) {
- currentSink.anchor(name);
- }
-
- /** {@inheritDoc} */
- @Override
- public void anchor(String name, SinkEventAttributes attributes) {
- currentSink.anchor(name, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void anchor_() {
- currentSink.anchor_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void article() {
- currentSink.article();
- }
-
- /** {@inheritDoc} */
- @Override
- public void article(SinkEventAttributes attributes) {
- currentSink.article(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void article_() {
- currentSink.article_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void author() {
- currentSink.author();
- }
-
- /** {@inheritDoc} */
- @Override
- public void author(SinkEventAttributes attributes) {
- currentSink.author(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void author_() {
- currentSink.author_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void blockquote() {
- currentSink.blockquote();
- }
-
- /** {@inheritDoc} */
- @Override
- public void blockquote(SinkEventAttributes attributes) {
- currentSink.blockquote(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void blockquote_() {
- currentSink.blockquote_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void body() {
- currentSink.body();
- }
-
- /** {@inheritDoc} */
- @Override
- public void body(SinkEventAttributes attributes) {
- currentSink.body(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void body_() {
- currentSink.body_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void bold() {
- currentSink.bold();
- }
-
- /** {@inheritDoc} */
- @Override
- public void bold_() {
- currentSink.bold_();
- }
-
/**
* Close all sinks
*/
@@ -278,204 +167,6 @@ public class RandomAccessSink implements Sink {
coreSink.close();
}
- /** {@inheritDoc} */
- @Override
- public void comment(String comment) {
- currentSink.comment(comment);
- }
-
- /** {@inheritDoc} */
- @Override
- public void content() {
- currentSink.content();
- }
-
- /** {@inheritDoc} */
- @Override
- public void content(SinkEventAttributes attributes) {
- currentSink.content(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void content_() {
- currentSink.content_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void data(String value) {
- currentSink.data(value);
- }
-
- /** {@inheritDoc} */
- @Override
- public void data(String value, SinkEventAttributes attributes) {
- currentSink.data(value, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void data_() {
- currentSink.data_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void date() {
- currentSink.date();
- }
-
- /** {@inheritDoc} */
- @Override
- public void date(SinkEventAttributes attributes) {
- currentSink.date(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void date_() {
- currentSink.date_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definedTerm() {
- currentSink.definedTerm();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definedTerm(SinkEventAttributes attributes) {
- currentSink.definedTerm(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void definedTerm_() {
- currentSink.definedTerm_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definition() {
- currentSink.definition();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definition(SinkEventAttributes attributes) {
- currentSink.definition(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionList() {
- currentSink.definitionList();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionList(SinkEventAttributes attributes) {
- currentSink.definitionList(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionListItem() {
- currentSink.definitionListItem();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionListItem(SinkEventAttributes attributes) {
- currentSink.definitionListItem(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionListItem_() {
- currentSink.definitionListItem_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definitionList_() {
- currentSink.definitionList_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void definition_() {
- currentSink.definition_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void division() {
- currentSink.division();
- }
-
- /** {@inheritDoc} */
- @Override
- public void division(SinkEventAttributes attributes) {
- currentSink.division(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void division_() {
- currentSink.division_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void figure() {
- currentSink.figure();
- }
-
- /** {@inheritDoc} */
- @Override
- public void figure(SinkEventAttributes attributes) {
- currentSink.figure(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void figureCaption() {
- currentSink.figureCaption();
- }
-
- /** {@inheritDoc} */
- @Override
- public void figureCaption(SinkEventAttributes attributes) {
- currentSink.figureCaption(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void figureCaption_() {
- currentSink.figureCaption_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void figureGraphics(String name) {
- currentSink.figureGraphics(name);
- }
-
- /** {@inheritDoc} */
- @Override
- public void figureGraphics(String src, SinkEventAttributes attributes) {
- currentSink.figureGraphics(src, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void figure_() {
- currentSink.figure_();
- }
-
/**
* Flush all sinks
*/
@@ -495,634 +186,4 @@ public class RandomAccessSink implements Sink {
}
coreSink.flush();
}
-
- /** {@inheritDoc} */
- @Override
- public void footer() {
- currentSink.footer();
- }
-
- /** {@inheritDoc} */
- @Override
- public void footer(SinkEventAttributes attributes) {
- currentSink.footer(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void footer_() {
- currentSink.footer_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void head() {
- currentSink.head();
- }
-
- /** {@inheritDoc} */
- @Override
- public void head(SinkEventAttributes attributes) {
- currentSink.head(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void head_() {
- currentSink.head_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void header() {
- currentSink.header();
- }
-
- /** {@inheritDoc} */
- @Override
- public void header(SinkEventAttributes attributes) {
- currentSink.header(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void header_() {
- currentSink.header_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void horizontalRule() {
- currentSink.horizontalRule();
- }
-
- /** {@inheritDoc} */
- @Override
- public void horizontalRule(SinkEventAttributes attributes) {
- currentSink.horizontalRule(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void inline() {
- currentSink.inline();
- }
-
- /** {@inheritDoc} */
- @Override
- public void inline(SinkEventAttributes attributes) {
- currentSink.inline(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void inline_() {
- currentSink.inline_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void italic() {
- currentSink.italic();
- }
-
- /** {@inheritDoc} */
- @Override
- public void italic_() {
- currentSink.italic_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void lineBreak() {
- currentSink.lineBreak();
- }
-
- /** {@inheritDoc} */
- @Override
- public void lineBreak(SinkEventAttributes attributes) {
- currentSink.lineBreak(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void lineBreakOpportunity() {
- currentSink.lineBreakOpportunity();
- }
-
- /** {@inheritDoc} */
- @Override
- public void lineBreakOpportunity(SinkEventAttributes attributes) {
- currentSink.lineBreakOpportunity(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void link(String name) {
- currentSink.link(name);
- }
-
- /** {@inheritDoc} */
- @Override
- public void link(String name, SinkEventAttributes attributes) {
- currentSink.link(name, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void link_() {
- currentSink.link_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void list() {
- currentSink.list();
- }
-
- /** {@inheritDoc} */
- @Override
- public void list(SinkEventAttributes attributes) {
- currentSink.list(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void listItem() {
- currentSink.listItem();
- }
-
- /** {@inheritDoc} */
- @Override
- public void listItem(SinkEventAttributes attributes) {
- currentSink.listItem(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void listItem_() {
- currentSink.listItem_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void list_() {
- currentSink.list_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void monospaced() {
- currentSink.monospaced();
- }
-
- /** {@inheritDoc} */
- @Override
- public void monospaced_() {
- currentSink.monospaced_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void navigation() {
- currentSink.navigation();
- }
-
- /** {@inheritDoc} */
- @Override
- public void navigation(SinkEventAttributes attributes) {
- currentSink.navigation(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void navigation_() {
- currentSink.navigation_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void nonBreakingSpace() {
- currentSink.nonBreakingSpace();
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedList(int numbering) {
- currentSink.numberedList(numbering);
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedList(int numbering, SinkEventAttributes attributes) {
- currentSink.numberedList(numbering, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedListItem() {
- currentSink.numberedListItem();
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedListItem(SinkEventAttributes attributes) {
- currentSink.numberedListItem(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedListItem_() {
- currentSink.numberedListItem_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void numberedList_() {
- currentSink.numberedList_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void pageBreak() {
- currentSink.pageBreak();
- }
-
- /** {@inheritDoc} */
- @Override
- public void paragraph() {
- currentSink.paragraph();
- }
-
- /** {@inheritDoc} */
- @Override
- public void paragraph(SinkEventAttributes attributes) {
- currentSink.paragraph(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void paragraph_() {
- currentSink.paragraph_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void rawText(String text) {
- currentSink.rawText(text);
- }
-
- /** {@inheritDoc} */
- @Override
- public void section(int level, SinkEventAttributes attributes) {
- currentSink.section(level, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void section1() {
- currentSink.section1();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section1_() {
- currentSink.section1_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section2() {
- currentSink.section2();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section2_() {
- currentSink.section2_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section3() {
- currentSink.section3();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section3_() {
- currentSink.section3_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section4() {
- currentSink.section4();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section4_() {
- currentSink.section4_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section5() {
- currentSink.section5();
- }
-
- /** {@inheritDoc} */
- @Override
- public void section5_() {
- currentSink.section5_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle() {
- currentSink.sectionTitle();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle(int level, SinkEventAttributes attributes) {
- currentSink.sectionTitle(level, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle1() {
- currentSink.sectionTitle1();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle1_() {
- currentSink.sectionTitle1_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle2() {
- currentSink.sectionTitle2();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle2_() {
- currentSink.sectionTitle2_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle3() {
- currentSink.sectionTitle3();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle3_() {
- currentSink.sectionTitle3_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle4() {
- currentSink.sectionTitle4();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle4_() {
- currentSink.sectionTitle4_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle5() {
- currentSink.sectionTitle5();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle5_() {
- currentSink.sectionTitle5_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle_() {
- currentSink.sectionTitle_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sectionTitle_(int level) {
- currentSink.sectionTitle_(level);
- }
-
- /** {@inheritDoc} */
- @Override
- public void section_(int level) {
- currentSink.section_(level);
- }
-
- /** {@inheritDoc} */
- @Override
- public void sidebar() {
- currentSink.sidebar();
- }
-
- /** {@inheritDoc} */
- @Override
- public void sidebar(SinkEventAttributes attributes) {
- currentSink.sidebar(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void sidebar_() {
- currentSink.sidebar_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void table() {
- currentSink.table();
- }
-
- /** {@inheritDoc} */
- @Override
- public void table(SinkEventAttributes attributes) {
- currentSink.table(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCaption() {
- currentSink.tableCaption();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCaption(SinkEventAttributes attributes) {
- currentSink.tableCaption(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCaption_() {
- currentSink.tableCaption_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCell() {
- currentSink.tableCell();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCell(SinkEventAttributes attributes) {
- currentSink.tableCell(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableCell_() {
- currentSink.tableCell_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableHeaderCell() {
- currentSink.tableHeaderCell();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableHeaderCell(SinkEventAttributes attributes) {
- currentSink.tableHeaderCell(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableHeaderCell_() {
- currentSink.tableHeaderCell_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRow() {
- currentSink.tableRow();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRow(SinkEventAttributes attributes) {
- currentSink.tableRow(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRow_() {
- currentSink.tableRow_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRows() {
- currentSink.tableRows();
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRows(int[] justification, boolean grid) {
- currentSink.tableRows(justification, grid);
- }
-
- /** {@inheritDoc} */
- @Override
- public void tableRows_() {
- currentSink.tableRows_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void table_() {
- currentSink.table_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void text(String text) {
- currentSink.text(text);
- }
-
- /** {@inheritDoc} */
- @Override
- public void text(String text, SinkEventAttributes attributes) {
- currentSink.text(text, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void time(String datetime) {
- currentSink.time(datetime);
- }
-
- /** {@inheritDoc} */
- @Override
- public void time(String datetime, SinkEventAttributes attributes) {
- currentSink.time(datetime, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void time_() {
- currentSink.time_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void title() {
- currentSink.title();
- }
-
- /** {@inheritDoc} */
- @Override
- public void title(SinkEventAttributes attributes) {
- currentSink.title(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void title_() {
- currentSink.title_();
- }
-
- /** {@inheritDoc} */
- @Override
- public void unknown(String name, Object[] requiredParams,
SinkEventAttributes attributes) {
- currentSink.unknown(name, requiredParams, attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void verbatim() {
- currentSink.verbatim();
- }
-
- /** {@inheritDoc} */
- @Override
- public void verbatim(SinkEventAttributes attributes) {
- currentSink.verbatim(attributes);
- }
-
- /** {@inheritDoc} */
- @Override
- public void verbatim_() {
- currentSink.verbatim_();
- }
}
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapper.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapper.java
new file mode 100644
index 00000000..21803311
--- /dev/null
+++ b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapper.java
@@ -0,0 +1,529 @@
+/*
+ * 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.
+ */
+package org.apache.maven.doxia.sink.impl;
+
+import org.apache.maven.doxia.parser.Parser;
+import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.doxia.sink.SinkEventAttributes;
+
+/**
+ * By default a {@link SinkWrapper} just delegates each method to the wrapped
sink's method.
+ * For certain sink methods a derived wrapper may modify the sink before/after
or instead of calling the delegate's method.
+ * Sink wrappers can either be registered manually via {@link
Parser#registerSinkWrapperFactory(int, SinkWrapperFactory)} or
+ * are automatically registered if provided as JSR330 component.
+ * In addition Sink wrappers can be used programmatically without an according
factory.
+ * @since 2.0.0
+ */
+public class SinkWrapper extends AbstractSink {
+
+ private Sink delegate;
+
+ public SinkWrapper(Sink delegate) {
+ super();
+ this.delegate = delegate;
+ }
+
+ public Sink getWrappedSink() {
+ return delegate;
+ }
+
+ public void setWrappedSink(Sink sink) {
+ delegate = sink;
+ }
+
+ @Override
+ public void head(SinkEventAttributes attributes) {
+ delegate.head(attributes);
+ }
+
+ @Override
+ public void head_() {
+ delegate.head_();
+ }
+
+ @Override
+ public void title(SinkEventAttributes attributes) {
+ delegate.title(attributes);
+ }
+
+ @Override
+ public void title_() {
+ delegate.title_();
+ }
+
+ @Override
+ public void author(SinkEventAttributes attributes) {
+ delegate.author(attributes);
+ }
+
+ @Override
+ public void author_() {
+ delegate.author_();
+ }
+
+ @Override
+ public void date(SinkEventAttributes attributes) {
+ delegate.date(attributes);
+ }
+
+ @Override
+ public void date_() {
+ delegate.date_();
+ }
+
+ @Override
+ public void body(SinkEventAttributes attributes) {
+ delegate.body(attributes);
+ }
+
+ @Override
+ public void body_() {
+ delegate.body_();
+ }
+
+ @Override
+ public void article(SinkEventAttributes attributes) {
+ delegate.article(attributes);
+ }
+
+ @Override
+ public void article_() {
+ delegate.article_();
+ }
+
+ @Override
+ public void navigation(SinkEventAttributes attributes) {
+ delegate.navigation(attributes);
+ }
+
+ @Override
+ public void navigation_() {
+ delegate.navigation_();
+ }
+
+ @Override
+ public void sidebar(SinkEventAttributes attributes) {
+ delegate.sidebar(attributes);
+ }
+
+ @Override
+ public void sidebar_() {
+ delegate.sidebar_();
+ }
+
+ @Override
+ public void section(int level, SinkEventAttributes attributes) {
+ delegate.section(level, attributes);
+ }
+
+ @Override
+ public void section_(int level) {
+ delegate.section_(level);
+ }
+
+ @Override
+ public void sectionTitle(int level, SinkEventAttributes attributes) {
+ delegate.sectionTitle(level, attributes);
+ }
+
+ @Override
+ public void sectionTitle_(int level) {
+ delegate.sectionTitle_(level);
+ }
+
+ @Override
+ public void header(SinkEventAttributes attributes) {
+ delegate.header(attributes);
+ }
+
+ @Override
+ public void header_() {
+ delegate.header_();
+ }
+
+ @Override
+ public void content(SinkEventAttributes attributes) {
+ delegate.content(attributes);
+ }
+
+ @Override
+ public void content_() {
+ delegate.content_();
+ }
+
+ @Override
+ public void footer(SinkEventAttributes attributes) {
+ delegate.footer(attributes);
+ }
+
+ @Override
+ public void footer_() {
+ delegate.footer_();
+ }
+
+ @Override
+ public void list(SinkEventAttributes attributes) {
+ delegate.list(attributes);
+ }
+
+ @Override
+ public void list_() {
+ delegate.list_();
+ }
+
+ @Override
+ public void listItem(SinkEventAttributes attributes) {
+ delegate.listItem(attributes);
+ }
+
+ @Override
+ public void listItem_() {
+ delegate.listItem_();
+ }
+
+ @Override
+ public void numberedList(int numbering, SinkEventAttributes attributes) {
+ delegate.numberedList(numbering, attributes);
+ }
+
+ @Override
+ public void numberedList_() {
+ delegate.numberedList_();
+ }
+
+ @Override
+ public void numberedListItem(SinkEventAttributes attributes) {
+ delegate.numberedListItem(attributes);
+ }
+
+ @Override
+ public void numberedListItem_() {
+ delegate.numberedListItem_();
+ }
+
+ @Override
+ public void definitionList(SinkEventAttributes attributes) {
+ delegate.definitionList(attributes);
+ }
+
+ @Override
+ public void definitionList_() {
+ delegate.definitionList_();
+ }
+
+ @Override
+ public void definitionListItem(SinkEventAttributes attributes) {
+ delegate.definitionListItem(attributes);
+ }
+
+ @Override
+ public void definitionListItem_() {
+ delegate.definitionListItem_();
+ }
+
+ @Override
+ public void definition(SinkEventAttributes attributes) {
+ delegate.definition(attributes);
+ }
+
+ @Override
+ public void definition_() {
+ delegate.definition_();
+ }
+
+ @Override
+ public void definedTerm(SinkEventAttributes attributes) {
+ delegate.definedTerm(attributes);
+ }
+
+ @Override
+ public void definedTerm_() {
+ delegate.definedTerm_();
+ }
+
+ @Override
+ public void figure(SinkEventAttributes attributes) {
+ delegate.figure(attributes);
+ }
+
+ @Override
+ public void figure_() {
+ delegate.figure_();
+ }
+
+ @Override
+ public void figureCaption(SinkEventAttributes attributes) {
+ delegate.figureCaption(attributes);
+ }
+
+ @Override
+ public void figureCaption_() {
+ delegate.figureCaption_();
+ }
+
+ @Override
+ public void figureGraphics(String src, SinkEventAttributes attributes) {
+ delegate.figureGraphics(src, attributes);
+ }
+
+ @Override
+ public void table(SinkEventAttributes attributes) {
+ delegate.table(attributes);
+ }
+
+ @Override
+ public void table_() {
+ delegate.table_();
+ }
+
+ @Override
+ public void tableRows(int[] justification, boolean grid) {
+ delegate.tableRows(justification, grid);
+ }
+
+ @Override
+ public void tableRows_() {
+ delegate.tableRows_();
+ }
+
+ @Override
+ public void tableRow(SinkEventAttributes attributes) {
+ delegate.tableRow(attributes);
+ }
+
+ @Override
+ public void tableRow_() {
+ delegate.tableRow_();
+ }
+
+ @Override
+ public void tableCell(SinkEventAttributes attributes) {
+ delegate.tableCell(attributes);
+ }
+
+ @Override
+ public void tableCell_() {
+ delegate.tableCell_();
+ }
+
+ @Override
+ public void tableHeaderCell(SinkEventAttributes attributes) {
+ delegate.tableHeaderCell(attributes);
+ }
+
+ @Override
+ public void tableHeaderCell_() {
+ delegate.tableHeaderCell_();
+ }
+
+ @Override
+ public void tableCaption(SinkEventAttributes attributes) {
+ delegate.tableCaption(attributes);
+ }
+
+ @Override
+ public void tableCaption_() {
+ delegate.tableCaption_();
+ }
+
+ @Override
+ public void paragraph(SinkEventAttributes attributes) {
+ delegate.paragraph(attributes);
+ }
+
+ @Override
+ public void paragraph_() {
+ delegate.paragraph_();
+ }
+
+ @Override
+ public void data(String value, SinkEventAttributes attributes) {
+ delegate.data(value, attributes);
+ }
+
+ @Override
+ public void data_() {
+ delegate.data_();
+ }
+
+ @Override
+ public void time(String datetime, SinkEventAttributes attributes) {
+ delegate.time(datetime, attributes);
+ }
+
+ @Override
+ public void time_() {
+ delegate.time_();
+ }
+
+ @Override
+ public void address(SinkEventAttributes attributes) {
+ delegate.address(attributes);
+ }
+
+ @Override
+ public void address_() {
+ delegate.address_();
+ }
+
+ @Override
+ public void blockquote(SinkEventAttributes attributes) {
+ delegate.blockquote(attributes);
+ }
+
+ @Override
+ public void blockquote_() {
+ delegate.blockquote_();
+ }
+
+ @Override
+ public void division(SinkEventAttributes attributes) {
+ delegate.division(attributes);
+ }
+
+ @Override
+ public void division_() {
+ delegate.division_();
+ }
+
+ @Override
+ public void verbatim(SinkEventAttributes attributes) {
+ delegate.verbatim(attributes);
+ }
+
+ @Override
+ public void verbatim_() {
+ delegate.verbatim_();
+ }
+
+ @Override
+ public void horizontalRule(SinkEventAttributes attributes) {
+ delegate.horizontalRule(attributes);
+ }
+
+ @Override
+ public void pageBreak() {
+ delegate.pageBreak();
+ }
+
+ @Override
+ public void anchor(String name, SinkEventAttributes attributes) {
+ delegate.anchor(name, attributes);
+ }
+
+ @Override
+ public void anchor_() {
+ delegate.anchor_();
+ }
+
+ @Override
+ public void link(String name, SinkEventAttributes attributes) {
+ delegate.link(name, attributes);
+ }
+
+ @Override
+ public void link_() {
+ delegate.link_();
+ }
+
+ @Override
+ public void inline(SinkEventAttributes attributes) {
+ delegate.inline(attributes);
+ }
+
+ @Override
+ public void inline_() {
+ delegate.inline_();
+ }
+
+ @Override
+ public void italic() {
+ delegate.italic();
+ }
+
+ @Override
+ public void italic_() {
+ delegate.italic_();
+ }
+
+ @Override
+ public void bold() {
+ delegate.bold();
+ }
+
+ @Override
+ public void bold_() {
+ delegate.bold_();
+ }
+
+ @Override
+ public void monospaced() {
+ delegate.monospaced();
+ }
+
+ @Override
+ public void monospaced_() {
+ delegate.monospaced_();
+ }
+
+ @Override
+ public void lineBreak(SinkEventAttributes attributes) {
+ delegate.lineBreak(attributes);
+ }
+
+ @Override
+ public void lineBreakOpportunity(SinkEventAttributes attributes) {
+ delegate.lineBreakOpportunity(attributes);
+ }
+
+ @Override
+ public void nonBreakingSpace() {
+ delegate.nonBreakingSpace();
+ }
+
+ @Override
+ public void text(String text, SinkEventAttributes attributes) {
+ delegate.text(text, attributes);
+ }
+
+ @Override
+ public void rawText(String text) {
+ delegate.rawText(text);
+ }
+
+ @Override
+ public void comment(String comment) {
+ delegate.comment(comment);
+ }
+
+ @Override
+ public void unknown(String name, Object[] requiredParams,
SinkEventAttributes attributes) {
+ delegate.unknown(name, requiredParams, attributes);
+ }
+
+ @Override
+ public void flush() {
+ delegate.flush();
+ }
+
+ @Override
+ public void close() {
+ delegate.close();
+ }
+}
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactory.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactory.java
new file mode 100644
index 00000000..354b1524
--- /dev/null
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+package org.apache.maven.doxia.sink.impl;
+
+import org.apache.maven.doxia.sink.Sink;
+
+/**
+ * A factory for a sink wrapping another sink.
+ * The delegate may either be the original sink or another wrapper.
+ * @since 2.0.0
+ */
+public interface SinkWrapperFactory {
+
+ /**
+ * By default all wrappers just delegate each method to the wrapped sink's
method.
+ * For certain Sink methods the wrapper may modify the sink before/after
or instead of calling the delegate's method.
+ * @param sink the delegate
+ * @return a new sink wrapping the given one
+ */
+ Sink createWrapper(Sink sink);
+
+ /**
+ * Determines the order of sink wrappers. The wrapper factory with the
highest priority is called first.
+ * @return the priority of this factory
+ */
+ int getPriority();
+}
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactoryComparator.java
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactoryComparator.java
new file mode 100644
index 00000000..37f2739c
--- /dev/null
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/sink/impl/SinkWrapperFactoryComparator.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.maven.doxia.sink.impl;
+
+import java.util.Comparator;
+
+/**
+ * Sorts the given {@link SinkWrapperFactory}s so that the one with the
highest priority comes first (i.e. order by descending priority)
+ * @since 2.0.0
+ */
+public final class SinkWrapperFactoryComparator implements
Comparator<SinkWrapperFactory> {
+
+ @Override
+ public int compare(SinkWrapperFactory o1, SinkWrapperFactory o2) {
+ return Integer.compare(o2.getPriority(), o1.getPriority());
+ }
+}
diff --git
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
index 5e1ffbd4..bfd95492 100644
---
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
+++
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/AbstractParserTest.java
@@ -20,13 +20,17 @@ package org.apache.maven.doxia.parser;
import java.io.IOException;
import java.io.Reader;
+import java.io.StringWriter;
import java.io.Writer;
import java.util.Iterator;
import org.apache.maven.doxia.AbstractModuleTest;
import org.apache.maven.doxia.sink.Sink;
+import org.apache.maven.doxia.sink.SinkEventAttributes;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
import org.apache.maven.doxia.sink.impl.SinkEventElement;
+import org.apache.maven.doxia.sink.impl.SinkWrapper;
+import org.apache.maven.doxia.sink.impl.SinkWrapperFactory;
import org.apache.maven.doxia.sink.impl.TextSink;
import org.apache.maven.doxia.sink.impl.WellformednessCheckingSink;
import org.junit.jupiter.api.Assertions;
@@ -96,18 +100,69 @@ public abstract class AbstractParserTest extends
AbstractModuleTest {
}
}
- protected static void assertSinkEquals(SinkEventElement element, String
name, Object... args) {
+ @Test
+ public final void testSinkWrapper() throws ParseException, IOException {
+ Parser parser = createParser();
+
+ parser.addSinkWrapperFactory(new SinkWrapperFactory() {
+
+ @Override
+ public Sink createWrapper(Sink sink) {
+ return new SinkWrapper(sink) {
+
+ @Override
+ public void text(String text, SinkEventAttributes
attributes) {
+ super.text("beforeWrapper1" + text + "afterWrapper1",
attributes);
+ }
+ };
+ }
+
+ @Override
+ public int getPriority() {
+ return 0;
+ }
+ });
+
+ parser.addSinkWrapperFactory(new SinkWrapperFactory() {
+
+ @Override
+ public Sink createWrapper(Sink sink) {
+ return new SinkWrapper(sink) {
+ @Override
+ public void text(String text, SinkEventAttributes
attributes) {
+ super.text("beforeWrapper2" + text + "afterWrapper2",
attributes);
+ }
+ };
+ }
+
+ @Override
+ public int getPriority() {
+ return 1;
+ }
+ });
+ try (StringWriter writer = new StringWriter();
+ Reader reader = getTestReader("test", outputExtension())) {
+ Sink sink = new TextSink(writer);
+ parser.parse(reader, sink);
+
+ // assert order of sink wrappers
+
assertTrue(writer.toString().contains("beforeWrapper2beforeWrapper1"));
+
assertTrue(writer.toString().contains("afterWrapper1afterWrapper2"));
+ }
+ }
+
+ public static void assertSinkEquals(SinkEventElement element, String name,
Object... args) {
Assertions.assertEquals(name, element.getName(), "Name of element
doesn't match");
Assertions.assertArrayEquals(args, element.getArgs(), "Arguments don't
match");
}
- protected static void assertSinkAttributeEquals(SinkEventElement element,
String name, String attr, String value) {
+ public static void assertSinkAttributeEquals(SinkEventElement element,
String name, String attr, String value) {
Assertions.assertEquals(name, element.getName());
SinkEventAttributeSet atts = (SinkEventAttributeSet)
element.getArgs()[0];
Assertions.assertEquals(value, atts.getAttribute(attr));
}
- protected static void assertSinkEquals(Iterator<SinkEventElement> it,
String... names) {
+ public static void assertSinkEquals(Iterator<SinkEventElement> it,
String... names) {
StringBuilder expected = new StringBuilder();
StringBuilder actual = new StringBuilder();
@@ -122,7 +177,7 @@ public abstract class AbstractParserTest extends
AbstractModuleTest {
Assertions.assertEquals(expected.toString(), actual.toString());
}
- protected static void assertSinkStartsWith(Iterator<SinkEventElement> it,
String... names) {
+ public static void assertSinkStartsWith(Iterator<SinkEventElement> it,
String... names) {
StringBuilder expected = new StringBuilder();
StringBuilder actual = new StringBuilder();
diff --git
a/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
b/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
index 36990f7a..1df6a41c 100644
---
a/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
+++
b/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java
@@ -199,7 +199,7 @@ public class AptParser extends AbstractTextParser
implements AptMarkup {
try {
this.source = new AptReaderSource(new StringReader(sourceContent),
reference);
- this.sink = sink;
+ this.sink = getWrappedSink(sink);
blockFileName = null;
diff --git
a/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
b/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
index c1dd98cd..559d3f2a 100644
---
a/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
+++
b/doxia-modules/doxia-module-fml/src/main/java/org/apache/maven/doxia/module/fml/FmlParser.java
@@ -105,7 +105,7 @@ public class FmlParser extends AbstractXmlParser implements
FmlMarkup {
// this populates faqs
super.parse(tmp, sink, reference);
- writeFaqs(sink);
+ writeFaqs(getWrappedSink(sink));
} finally {
this.faqs = null;
this.sourceContent = null;
diff --git
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
index 610f4dc4..9c229ccf 100644
---
a/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
+++
b/doxia-modules/doxia-module-markdown/src/main/java/org/apache/maven/doxia/module/markdown/MarkdownParser.java
@@ -172,7 +172,7 @@ public class MarkdownParser extends AbstractTextParser
implements TextMarkup {
String html = toHtml(source);
// then HTML to Sink API
- parser.parse(html, sink);
+ parser.parse(html, getWrappedSink(sink));
} catch (IOException e) {
throw new ParseException("Failed reading Markdown source
document", e);
}