You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2023/01/20 21:42:53 UTC

[maven-doxia-converter] 01/01: DOXIATOOLS-75 improved directory input support

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/improve-input-directory-support
in repository https://gitbox.apache.org/repos/asf/maven-doxia-converter.git

commit 0b917a749ae062de0efc1f819de8608cc5cfac47
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Jan 20 22:42:46 2023 +0100

    DOXIATOOLS-75 improved directory input support
    
    Replace extensions instead of appending it
    Keep subdirectory structure from "in" in "out"
    Define extensions per format
---
 pom.xml                                            |   2 +-
 .../java/org/apache/maven/doxia/Converter.java     |  10 -
 .../org/apache/maven/doxia/DefaultConverter.java   | 347 +++++++++++++--------
 .../org/apache/maven/doxia/cli/CLIManager.java     |  11 +-
 .../org/apache/maven/doxia/cli/ConverterCli.java   |   6 +-
 .../org/apache/maven/doxia/util/ConverterUtil.java | 104 ------
 .../maven/doxia/wrapper/AbstractFileWrapper.java   |   7 +-
 .../maven/doxia/wrapper/AbstractWrapper.java       | 118 -------
 .../maven/doxia/wrapper/InputFileWrapper.java      |  37 ++-
 .../maven/doxia/wrapper/InputReaderWrapper.java    |  23 +-
 .../maven/doxia/wrapper/OutputFileWrapper.java     |  26 +-
 .../maven/doxia/wrapper/OutputStreamWrapper.java   |  26 +-
 .../java/org/apache/maven/doxia/ConverterTest.java | 166 +++++-----
 src/test/resources/unit/apt/child/test.apt         |   1 +
 14 files changed, 389 insertions(+), 495 deletions(-)

diff --git a/pom.xml b/pom.xml
index f44216b..9f91aec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -213,7 +213,7 @@ under the License.
           <artifactId>apache-rat-plugin</artifactId>
           <configuration>
             <excludes combine.children="append">
-              <exclude>src/test/resources/unit/*/test.*</exclude>
+              <exclude>src/test/resources/unit/**/test.*</exclude>
               <exclude>src/test/resources/book-1/section-*.apt</exclude>
             </excludes>            
           </configuration>
diff --git a/src/main/java/org/apache/maven/doxia/Converter.java b/src/main/java/org/apache/maven/doxia/Converter.java
index 3c625e4..bd16840 100644
--- a/src/main/java/org/apache/maven/doxia/Converter.java
+++ b/src/main/java/org/apache/maven/doxia/Converter.java
@@ -33,16 +33,6 @@ import org.apache.maven.doxia.wrapper.OutputStreamWrapper;
 public interface Converter
     extends LogEnabled
 {
-    /**
-     * @return a not null array containing supported input formats, i.e. <code>apt</code>.
-     */
-    String[] getInputFormats();
-
-    /**
-     * @return a not null array containing supported output formats, i.e. <code>xhtml</code>.
-     */
-    String[] getOutputFormats();
-
     /**
      * @param input an input file wrapper, not null.
      * @param output an output file wrapper, not null.
diff --git a/src/main/java/org/apache/maven/doxia/DefaultConverter.java b/src/main/java/org/apache/maven/doxia/DefaultConverter.java
index 04f76b2..34fa414 100644
--- a/src/main/java/org/apache/maven/doxia/DefaultConverter.java
+++ b/src/main/java/org/apache/maven/doxia/DefaultConverter.java
@@ -29,13 +29,12 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
 import java.io.Writer;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.maven.doxia.logging.Log;
 import org.apache.maven.doxia.logging.SystemStreamLog;
@@ -43,7 +42,6 @@ import org.apache.maven.doxia.parser.ParseException;
 import org.apache.maven.doxia.parser.Parser;
 import org.apache.maven.doxia.sink.Sink;
 import org.apache.maven.doxia.sink.SinkFactory;
-import org.apache.maven.doxia.util.ConverterUtil;
 import org.apache.maven.doxia.wrapper.InputFileWrapper;
 import org.apache.maven.doxia.wrapper.InputReaderWrapper;
 import org.apache.maven.doxia.wrapper.OutputFileWrapper;
@@ -55,6 +53,7 @@ import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.PlexusContainerException;
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.PathTool;
 import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.SelectorUtils;
 import org.codehaus.plexus.util.StringUtils;
@@ -96,10 +95,6 @@ public class DefaultConverter
 
     private static final String MARKDOWN_PARSER = "markdown";
 
-    /** Supported input format, i.e. supported Doxia parser */
-    public static final String[] SUPPORTED_FROM_FORMAT =
-        { APT_PARSER, CONFLUENCE_PARSER, DOCBOOK_PARSER, FML_PARSER, MARKDOWN_PARSER, TWIKI_PARSER,
-            XDOC_PARSER, XHTML_PARSER, XHTML5_PARSER };
 
     private static final String APT_SINK = "apt";
 
@@ -125,10 +120,173 @@ public class DefaultConverter
 
     private static final String MARKDOWN_SINK = "markdown";
 
-    /** Supported output format, i.e. supported Doxia Sink */
-    public static final String[] SUPPORTED_TO_FORMAT =
-        { APT_SINK, CONFLUENCE_SINK, DOCBOOK_SINK, FO_SINK, ITEXT_SINK, LATEX_SINK, MARKDOWN_SINK, RTF_SINK, TWIKI_SINK,
-            XDOC_SINK, XHTML_SINK, XHTML5_SINK };
+    /**
+     * All supported source formats
+     */
+    public enum ParserFormat
+    {
+        APT( APT_PARSER, "apt" ),
+        CONFLUENCE( CONFLUENCE_PARSER, "confluence" ),
+        DOCBOOK( DOCBOOK_PARSER, "dbk", "article" ),
+        FML( FML_PARSER, "fml", "faqs" ),
+        TWIKI( TWIKI_PARSER, "twiki" ),
+        XDOC( XDOC_PARSER, "xml", "document" ),
+        XHTML( XHTML_PARSER, "html", "html" ),
+        XHTML5( XHTML5_PARSER, "html" ), // no autodetect support
+        MARKDOWN( MARKDOWN_PARSER, "md" );
+
+        private final String parserName;
+        private final String extension;
+        private final String firstElement;
+
+        ParserFormat( String parserName, String extension )
+        {
+            this( parserName, extension, null );
+        }
+
+        ParserFormat( String parserName, String extension, String firstElement )
+        {
+            this.parserName = parserName;
+            this.extension = extension;
+            this.firstElement = firstElement;
+        }
+
+        /**
+         * 
+         * @return the primary extension used with this format
+         */
+        public String getExtension()
+        {
+            return extension;
+        }
+
+        /**
+         * 
+         * @return {@code true} in case this format is XML based
+         */
+        public boolean isXml()
+        {
+            return firstElement != null;
+        }
+
+        /**
+         * @param plexus not null
+         * @return an instance of <code>Parser</code> depending on the format.
+         * @throws ComponentLookupException if could not find the Parser for the given format.
+         * @throws IllegalArgumentException if any parameter is null
+         */
+        public Parser getParser( PlexusContainer plexus )
+            throws ComponentLookupException
+        {
+            Objects.requireNonNull( plexus, "plexus is required" );
+
+            return (Parser) plexus.lookup( Parser.ROLE, parserName );
+        }
+
+        /**
+         * Auto detect Doxia format for the given file depending:
+         * <ul>
+         * <li>the file name for TextMarkup based Doxia files</li>
+         * <li>the file content for XMLMarkup based Doxia files</li>
+         * </ul>
+         *
+         * @param f not null file
+         * @param encoding a not null encoding.
+         * @return the detected encoding from f.
+         * @throws IllegalArgumentException if f is not a file.
+         * @throws UnsupportedOperationException if could not detect the Doxia format.
+         */
+        static ParserFormat autoDetectFormat( File f, String encoding )
+        {
+            if ( !f.isFile() )
+            {
+                throw new IllegalArgumentException( "The file '" + f.getAbsolutePath()
+                    + "' is not a file, could not detect format." );
+            }
+
+            for ( ParserFormat format : EnumSet.allOf( ParserFormat.class ) )
+            {
+                if ( format.isXml() )
+                {
+                    // Handle Doxia xml files
+                    String firstTag = getFirstTag( f );
+                    if ( firstTag == null )
+                    {
+                        //noinspection UnnecessaryContinue
+                        continue;
+                    }
+                    if ( firstTag.equals( format.firstElement ) )
+                    {
+                        return format;
+                    }
+                }
+                else
+                {
+                    if ( hasFileExtensionIgnoreCase( f.getName(), format.getExtension() ) )
+                    {
+                        return format;
+                    }
+                }
+            }
+            throw new UnsupportedOperationException(
+                    format( "Could not detect the Doxia format for file: %s\n Specify explicitly the Doxia format.",
+                            f.getAbsolutePath() ) );
+        }
+    }
+
+    /**
+     * All supported target formats.
+     */
+    public enum SinkFormat
+    {
+        APT( APT_SINK, "apt", false ),
+        CONFLUENCE( CONFLUENCE_SINK, "confluence", false ),
+        DOCBOOK( DOCBOOK_SINK, "dbk", false ),
+        FO( FO_SINK, "fo", true ),
+        ITEXT( ITEXT_SINK, "itext", false ),
+        LATEXT( LATEX_SINK, "tex", false ),
+        RTF( RTF_SINK, "rtf", false ),
+        TWIKI( TWIKI_SINK, "twiki", false ),
+        XDOC( XDOC_SINK, "xdoc", true ),
+        XHTML( XHTML_SINK, "html", true ),
+        XHTML5( XHTML5_SINK, "html", true ),
+        MARKDOWN( MARKDOWN_SINK, "md", false );
+
+        private final String sinkName;
+        private final String extension;
+        private final boolean isXml;
+
+        SinkFormat( String sinkName, String extension, boolean isXml )
+        {
+            this.sinkName = sinkName;
+            this.extension = extension;
+            this.isXml = isXml;
+        }
+
+        public String getExtension()
+        {
+            return extension;
+        }
+
+        /**
+         * @param plexus not null
+         * @return an instance of <code>SinkFactory</code> depending on the given format.
+         * @throws ComponentLookupException if could not find the SinkFactory for the given format.
+         * @throws IllegalArgumentException if any parameter is null
+         */
+        public SinkFactory getSinkFactory( PlexusContainer plexus )
+            throws ComponentLookupException
+        {
+            Objects.requireNonNull( plexus, "plexus is required" );
+
+            return (SinkFactory) plexus.lookup( SinkFactory.ROLE, sinkName );
+        }
+
+        boolean isXml()
+        {
+            return isXml;
+        }
+    }
 
     /** Flag to format the generated files, actually only for XML based sinks. */
     private boolean formatOutput;
@@ -162,20 +320,6 @@ public class DefaultConverter
         return log;
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public String[] getInputFormats()
-    {
-        return SUPPORTED_FROM_FORMAT;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String[] getOutputFormats()
-    {
-        return SUPPORTED_TO_FORMAT;
-    }
-
     /** {@inheritDoc} */
     @Override
     public void convert( InputFileWrapper input, OutputFileWrapper output )
@@ -204,7 +348,7 @@ public class DefaultConverter
                 List<File> files;
                 try
                 {
-                    files = FileUtils.getFiles( input.getFile(), "**/*." + input.getFormat(),
+                    files = FileUtils.getFiles( input.getFile(), "**/*." + input.getFormat().getExtension(),
                                             StringUtils.join( FileUtils.getDefaultExcludes(), ", " ) );
                 }
                 catch ( IOException e )
@@ -218,7 +362,9 @@ public class DefaultConverter
 
                 for ( File f : files )
                 {
-                    parse( f, input.getEncoding(), input.getFormat(), output );
+                    File relativeOutputDirectory = new File( 
+                            PathTool.getRelativeFilePath( input.getFile().getAbsolutePath(), f.getParent() ) );
+                    parse( f, input.getEncoding(), input.getFormat(), output, relativeOutputDirectory );
                 }
             }
         }
@@ -250,7 +396,7 @@ public class DefaultConverter
             Parser parser;
             try
             {
-                parser = ConverterUtil.getParser( plexus, input.getFormat(), SUPPORTED_FROM_FORMAT );
+                parser = input.getFormat().getParser( plexus );
                 parser.enableLogging( log );
             }
             catch ( ComponentLookupException e )
@@ -266,7 +412,7 @@ public class DefaultConverter
             SinkFactory sinkFactory;
             try
             {
-                sinkFactory = ConverterUtil.getSinkFactory( plexus, output.getFormat(), SUPPORTED_TO_FORMAT );
+                sinkFactory = output.getFormat().getSinkFactory( plexus );
             }
             catch ( ComponentLookupException e )
             {
@@ -311,19 +457,38 @@ public class DefaultConverter
     /**
      * @param inputFile a not null existing file.
      * @param inputEncoding a not null supported encoding or {@link InputFileWrapper#AUTO_ENCODING}
-     * @param inputFormat  a not null supported format or {@link InputFileWrapper#AUTO_FORMAT}
+     * @param parserFormat  a not null supported format or {@link InputFileWrapper#AUTO_FORMAT}
+     * @param output not null OutputFileWrapper object
+     * @throws ConverterException if any
+     * @throws UnsupportedFormatException if any
+     */
+    private void parse( File inputFile, String inputEncoding, ParserFormat parserFormat, OutputFileWrapper output )
+        throws ConverterException, UnsupportedFormatException
+    {
+        parse( inputFile, inputEncoding, parserFormat, output, null );
+    }
+
+    /**
+     * @param inputFile a not null existing file.
+     * @param inputEncoding a not null supported encoding or {@link InputFileWrapper#AUTO_ENCODING}
+     * @param parserFormat  a not null supported format or {@link InputFileWrapper#AUTO_FORMAT}
      * @param output not null OutputFileWrapper object
+     * @param relativeOutputDirectory the relative output directory (may be null, created if it does not exist yet)
      * @throws ConverterException if any
      * @throws UnsupportedFormatException if any
      */
-    private void parse( File inputFile, String inputEncoding, String inputFormat, OutputFileWrapper output )
+    private void parse( File inputFile, String inputEncoding, ParserFormat parserFormat, OutputFileWrapper output,
+            File relativeOutputDirectory )
         throws ConverterException, UnsupportedFormatException
     {
+        File outputDirectoryOrFile = relativeOutputDirectory != null 
+                ? new File( output.getFile(), relativeOutputDirectory.getPath() ) 
+                : output.getFile();
         if ( getLog().isDebugEnabled() )
         {
             getLog().debug(
                             "Parsing file from '" + inputFile.getAbsolutePath() + "' with the encoding '"
-                                + inputEncoding + "' to '" + output.getFile().getAbsolutePath()
+                                + inputEncoding + "' to '" + outputDirectoryOrFile.getAbsolutePath()
                                 + "' with the encoding '" + output.getEncoding() + "'" );
         }
 
@@ -336,19 +501,19 @@ public class DefaultConverter
             }
         }
 
-        if ( InputFileWrapper.AUTO_FORMAT.equals( inputFormat ) )
+        if ( parserFormat == null )
         {
-            inputFormat = autoDetectFormat( inputFile, inputEncoding );
+            parserFormat = ParserFormat.autoDetectFormat( inputFile, inputEncoding );
             if ( getLog().isDebugEnabled() )
             {
-                getLog().debug( "Auto detect input format: " + inputFormat );
+                getLog().debug( "Auto detect input format: " + parserFormat );
             }
         }
 
         Parser parser;
         try
         {
-            parser = ConverterUtil.getParser( plexus, inputFormat, SUPPORTED_FROM_FORMAT );
+            parser = parserFormat.getParser( plexus );
             parser.enableLogging( log );
         }
         catch ( ComponentLookupException e )
@@ -357,23 +522,19 @@ public class DefaultConverter
         }
 
         File outputFile;
-        if ( output.getFile().isDirectory() )
+        if ( outputDirectoryOrFile.isDirectory() 
+             || !SelectorUtils.match( "**.*", output.getFile().getName() ) 
+             || relativeOutputDirectory != null )
         {
-            outputFile = new File( output.getFile(), inputFile.getName() + "." + output.getFormat() );
+            // assume it is a directory
+            outputDirectoryOrFile.mkdirs();
+            outputFile = new File( outputDirectoryOrFile, 
+                    FileUtils.removeExtension( inputFile.getName() ) + "." + output.getFormat().getExtension() );
         }
         else
         {
-            if ( !SelectorUtils.match( "**.*", output.getFile().getName() ) )
-            {
-                // assume it is a directory
-                output.getFile().mkdirs();
-                outputFile = new File( output.getFile(), inputFile.getName() + "." + output.getFormat() );
-            }
-            else
-            {
-                output.getFile().getParentFile().mkdirs();
-                outputFile = output.getFile();
-            }
+            outputDirectoryOrFile.getParentFile().mkdirs();
+            outputFile = output.getFile();
         }
 
         Reader reader;
@@ -403,7 +564,7 @@ public class DefaultConverter
         SinkFactory sinkFactory;
         try
         {
-            sinkFactory = ConverterUtil.getSinkFactory( plexus, output.getFormat(), SUPPORTED_TO_FORMAT );
+            sinkFactory = output.getFormat().getSinkFactory( plexus );
         }
         catch ( ComponentLookupException e )
         {
@@ -441,13 +602,11 @@ public class DefaultConverter
 
         parse( parser, reader, sink );
 
-        if ( formatOutput && ( DOCBOOK_SINK.equals( output.getFormat() ) || FO_SINK.equals( output.getFormat() )
-            || ITEXT_SINK.equals( output.getFormat() ) || XDOC_SINK.equals( output.getFormat() )
-            || XHTML_SINK.equals( output.getFormat() ) || XHTML5_SINK.equals( output.getFormat() ) ) )
+        if ( formatOutput && output.getFormat().isXml() )
         {
             // format all xml files excluding docbook which is buggy
             // TODO Add doc book format
-            if ( DOCBOOK_SINK.equals( output.getFormat() ) || DOCBOOK_PARSER.equals( inputFormat ) )
+            if ( DOCBOOK_SINK.equals( output.getFormat() ) || DOCBOOK_PARSER.equals( parserFormat ) )
             {
                 return;
             }
@@ -569,88 +728,18 @@ public class DefaultConverter
                 + "Specify explicitly the encoding.", f.getAbsolutePath() ) );
     }
 
-    /**
-     * Auto detect Doxia format for the given file depending:
-     * <ul>
-     * <li>the file name for TextMarkup based Doxia files</li>
-     * <li>the file content for XMLMarkup based Doxia files</li>
-     * </ul>
-     *
-     * @param f not null file
-     * @param encoding a not null encoding.
-     * @return the detected encoding from f.
-     * @throws IllegalArgumentException if f is not a file.
-     * @throws UnsupportedOperationException if could not detect the Doxia format.
-     */
-    static String autoDetectFormat( File f, String encoding )
-    {
-        if ( !f.isFile() )
-        {
-            throw new IllegalArgumentException( "The file '" + f.getAbsolutePath()
-                + "' is not a file, could not detect format." );
-        }
-
-        for ( String supportedFromFormat : SUPPORTED_FROM_FORMAT )
-        {
-            // Handle Doxia text files
-            if ( APT_PARSER.equalsIgnoreCase( supportedFromFormat ) && isDoxiaFileName( f, supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-            else if ( CONFLUENCE_PARSER.equalsIgnoreCase( supportedFromFormat ) && isDoxiaFileName( f,
-                    supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-            else if ( TWIKI_PARSER.equalsIgnoreCase( supportedFromFormat ) && isDoxiaFileName( f,
-                    supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-
-            // Handle Doxia xml files
-            String firstTag = getFirstTag( f );
-            if ( firstTag == null )
-            {
-                //noinspection UnnecessaryContinue
-                continue;
-            }
-            else if ( "article".equals( firstTag ) && DOCBOOK_PARSER.equalsIgnoreCase( supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-            else if ( "faqs".equals( firstTag ) && FML_PARSER.equalsIgnoreCase( supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-            else if ( "document".equals( firstTag ) && XDOC_PARSER.equalsIgnoreCase( supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-            else if ( "html".equals( firstTag ) && XHTML_PARSER.equalsIgnoreCase( supportedFromFormat ) )
-            {
-                return supportedFromFormat;
-            }
-        }
-
-        throw new UnsupportedOperationException(
-                format( "Could not detect the Doxia format for file: %s\n Specify explicitly the Doxia format.",
-                        f.getAbsolutePath() ) );
-    }
+    
 
     /**
      * @param f not null
      * @param format could be null
-     * @return <code>true</code> if the file name computes the format.
+     * @return <code>true</code> if the file extension matches
      */
-    private static boolean isDoxiaFileName( File f, String format )
+    private static boolean hasFileExtensionIgnoreCase( String name, String extension )
     {
-        Objects.requireNonNull( f, "f is required." );
-
-        Pattern pattern = Pattern.compile( "(.*?)\\." + format.toLowerCase( Locale.ENGLISH ) + "$" );
-        Matcher matcher = pattern.matcher( f.getName().toLowerCase( Locale.ENGLISH ) );
+        Objects.requireNonNull( name, "name is required." );
 
-        return matcher.matches();
+        return extension.equals( FileUtils.getExtension( name.toLowerCase( Locale.ENGLISH ) ) );
     }
 
     /**
diff --git a/src/main/java/org/apache/maven/doxia/cli/CLIManager.java b/src/main/java/org/apache/maven/doxia/cli/CLIManager.java
index 85756de..71223a2 100644
--- a/src/main/java/org/apache/maven/doxia/cli/CLIManager.java
+++ b/src/main/java/org/apache/maven/doxia/cli/CLIManager.java
@@ -19,6 +19,9 @@ package org.apache.maven.doxia.cli;
  * under the License.
  */
 
+import java.util.EnumSet;
+import java.util.stream.Collectors;
+
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.HelpFormatter;
@@ -159,8 +162,12 @@ class CLIManager
 
     private static String getSupportedFormat()
     {
-        return "\nSupported Formats:\n from: " + join( DefaultConverter.SUPPORTED_FROM_FORMAT, ", " )
-            + " or autodetect" + "\n to:   " + join( DefaultConverter.SUPPORTED_TO_FORMAT, ", " )
+        String fromFormats = EnumSet.allOf( DefaultConverter.ParserFormat.class ).stream()
+                .map( DefaultConverter.ParserFormat::toString ).collect( Collectors.joining( "," ) );
+        String toFormats = EnumSet.allOf( DefaultConverter.SinkFormat.class ).stream()
+                .map( DefaultConverter.SinkFormat::toString ).collect( Collectors.joining( "," ) );
+        return "\nSupported Formats:\n from: " + fromFormats
+            + " or auto" + "\n to:   " + toFormats
             + "\n";
     }
 
diff --git a/src/main/java/org/apache/maven/doxia/cli/ConverterCli.java b/src/main/java/org/apache/maven/doxia/cli/ConverterCli.java
index 27a169b..6a804f9 100644
--- a/src/main/java/org/apache/maven/doxia/cli/ConverterCli.java
+++ b/src/main/java/org/apache/maven/doxia/cli/ConverterCli.java
@@ -124,13 +124,11 @@ public class ConverterCli
             input =
                 InputFileWrapper.valueOf( commandLine.getOptionValue( CLIManager.IN ),
                                           commandLine.getOptionValue( CLIManager.FROM ),
-                                          commandLine.getOptionValue( CLIManager.INENCODING ),
-                                          converter.getInputFormats() );
+                                          commandLine.getOptionValue( CLIManager.INENCODING ) );
             output =
                 OutputFileWrapper.valueOf( commandLine.getOptionValue( CLIManager.OUT ),
                                            commandLine.getOptionValue( CLIManager.TO ),
-                                           commandLine.getOptionValue( CLIManager.OUTENCODING ),
-                                           converter.getOutputFormats() );
+                                           commandLine.getOptionValue( CLIManager.OUTENCODING ) );
         }
         catch ( IllegalArgumentException e )
         {
diff --git a/src/main/java/org/apache/maven/doxia/util/ConverterUtil.java b/src/main/java/org/apache/maven/doxia/util/ConverterUtil.java
deleted file mode 100644
index 18983d6..0000000
--- a/src/main/java/org/apache/maven/doxia/util/ConverterUtil.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.apache.maven.doxia.util;
-
-/*
- * 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 org.apache.maven.doxia.UnsupportedFormatException;
-import org.apache.maven.doxia.parser.Parser;
-import org.apache.maven.doxia.sink.SinkFactory;
-import org.codehaus.plexus.PlexusContainer;
-import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
-
-import java.util.Objects;
-
-/**
- * Utility class to play with Doxia objects.
- *
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
- */
-public class ConverterUtil
-{
-    /**
-     * @param plexus not null
-     * @param format not null
-     * @param supportedFormats not null
-     * @return an instance of <code>Parser</code> depending on the format.
-     * @throws ComponentLookupException if could not find the Parser for the given format.
-     * @throws UnsupportedFormatException if the found parser is not instantiated.
-     * @throws IllegalArgumentException if any parameter is null
-     */
-    public static Parser getParser( PlexusContainer plexus, String format, String[] supportedFormats )
-        throws ComponentLookupException, UnsupportedFormatException
-    {
-        Objects.requireNonNull( plexus, "plexus is required" );
-        Objects.requireNonNull( format, "format is required" );
-        Objects.requireNonNull( supportedFormats, "supportedFormats is required" );
-
-        Parser parser = null;
-
-        for ( String supportedFormat : supportedFormats )
-        {
-            if ( format.equalsIgnoreCase( supportedFormat ) )
-            {
-                parser = (Parser) plexus.lookup( Parser.ROLE, format );
-            }
-        }
-
-        if ( parser == null )
-        {
-            throw new UnsupportedFormatException( format, supportedFormats );
-        }
-
-        return parser;
-    }
-
-    /**
-     * @param plexus not null
-     * @param format not null
-     * @param supportedFormats not null
-     * @return an instance of <code>SinkFactory</code> depending on the given format.
-     * @throws ComponentLookupException if could not find the SinkFactory for the given format.
-     * @throws UnsupportedFormatException if the found sink is not instantiated.
-     * @throws IllegalArgumentException if any parameter is null
-     */
-    public static SinkFactory getSinkFactory( PlexusContainer plexus, String format, String[] supportedFormats )
-        throws ComponentLookupException, UnsupportedFormatException
-    {
-        Objects.requireNonNull( plexus, "plexus is required" );
-        Objects.requireNonNull( format, "format is required" );
-        Objects.requireNonNull( supportedFormats, "supportedFormats is required" );
-
-        SinkFactory factory = null;
-
-        for ( String supportedFormat : supportedFormats )
-        {
-            if ( format.equalsIgnoreCase( supportedFormat ) )
-            {
-                factory = (SinkFactory) plexus.lookup( SinkFactory.ROLE, format );
-            }
-        }
-
-        if ( factory == null )
-        {
-            throw new UnsupportedFormatException( format, supportedFormats );
-        }
-
-        return factory;
-    }
-}
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/AbstractFileWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/AbstractFileWrapper.java
index 9936d91..961542a 100644
--- a/src/main/java/org/apache/maven/doxia/wrapper/AbstractFileWrapper.java
+++ b/src/main/java/org/apache/maven/doxia/wrapper/AbstractFileWrapper.java
@@ -37,7 +37,6 @@ import static org.codehaus.plexus.util.StringUtils.isNotEmpty;
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  */
 abstract class AbstractFileWrapper
-    extends AbstractWrapper
 {
     public static final String AUTO_ENCODING = "auto";
 
@@ -48,17 +47,13 @@ abstract class AbstractFileWrapper
     /**
      *
      * @param absolutePath not null
-     * @param format could be null
      * @param encoding could be null
-     * @param supportedFormat not null
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      * @throws IllegalArgumentException if any
      */
-    AbstractFileWrapper( String absolutePath, String format, String encoding, String[] supportedFormat )
+    AbstractFileWrapper( String absolutePath, String encoding )
         throws UnsupportedEncodingException
     {
-        super( format, supportedFormat );
-
         if ( isEmpty( absolutePath ) )
         {
             throw new IllegalArgumentException( "absolutePath is required" );
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/AbstractWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/AbstractWrapper.java
deleted file mode 100644
index f6e759a..0000000
--- a/src/main/java/org/apache/maven/doxia/wrapper/AbstractWrapper.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.apache.maven.doxia.wrapper;
-
-/*
- * 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.Serializable;
-import java.util.Objects;
-
-import static org.codehaus.plexus.util.StringUtils.isNotEmpty;
-
-/**
- * Abstract wrapper for Doxia converter.
- *
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
- */
-abstract class AbstractWrapper
-    implements Serializable
-{
-    public static final String AUTO_FORMAT = "auto";
-
-    private String format;
-
-    private String[] supportedFormat;
-
-    /**
-     * @param format could be null.
-     * @param supportedFormat not null.
-     * @throws IllegalArgumentException if supportedFormat is null.
-     */
-    AbstractWrapper( String format, String[] supportedFormat )
-    {
-        this.format = ( isNotEmpty( format ) ? format : AUTO_FORMAT );
-        if ( supportedFormat == null )
-        {
-            throw new IllegalArgumentException( "supportedFormat is required" );
-        }
-        this.supportedFormat = supportedFormat;
-    }
-
-    /**
-     * @return the wanted format.
-     */
-    public String getFormat()
-    {
-        return this.format;
-    }
-
-    /**
-     * @param format The wanted format.
-     */
-    void setFormat( String format )
-    {
-        this.format = format;
-    }
-
-    /**
-     * @return the supportedFormat
-     */
-    public String[] getSupportedFormat()
-    {
-        return supportedFormat;
-    }
-
-    /**
-     * @param supportedFormat the supportedFormat to set
-     */
-    void setSupportedFormat( String[] supportedFormat )
-    {
-        this.supportedFormat = supportedFormat;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public boolean equals( Object other )
-    {
-        if ( this == other )
-        {
-            return true;
-        }
-        if ( other == null || getClass() != other.getClass() )
-        {
-            return false;
-        }
-
-        AbstractWrapper that = (AbstractWrapper) other;
-        return Objects.equals( getFormat(), that.getFormat() );
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public int hashCode()
-    {
-        return Objects.hash( getFormat() );
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public String toString()
-    {
-        return "format = '" + getFormat() + "'";
-    }
-}
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/InputFileWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/InputFileWrapper.java
index fdedd88..b25f839 100644
--- a/src/main/java/org/apache/maven/doxia/wrapper/InputFileWrapper.java
+++ b/src/main/java/org/apache/maven/doxia/wrapper/InputFileWrapper.java
@@ -22,6 +22,9 @@ package org.apache.maven.doxia.wrapper;
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
 
+import org.apache.maven.doxia.DefaultConverter;
+import org.codehaus.plexus.util.WriterFactory;
+
 /**
  * Wrapper for an input file.
  *
@@ -33,6 +36,8 @@ public class InputFileWrapper
     /** serialVersionUID */
     static final long serialVersionUID = 6510443036267371188L;
 
+    private final DefaultConverter.ParserFormat format;
+
     /**
      * Private constructor.
      *
@@ -43,15 +48,28 @@ public class InputFileWrapper
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      * @throws FileNotFoundException if the file for absolutePath is not found.
      */
-    private InputFileWrapper( String absolutePath, String format, String charsetName, String[] supportedFormat )
+    private InputFileWrapper( String absolutePath, String format, String charsetName )
         throws UnsupportedEncodingException, FileNotFoundException
     {
-        super( absolutePath, format, charsetName, supportedFormat );
+        super( absolutePath, charsetName );
 
+        if ( format == null )
+        {
+            this.format = null;
+        }
+        else 
+        {
+            this.format = DefaultConverter.ParserFormat.valueOf( format.toUpperCase() );
+        }
         if ( !getFile().exists() )
         {
             throw new FileNotFoundException( "The file '" + getFile().getAbsolutePath() + "' doesn't exist." );
         }
+        if ( getFile().isDirectory() && this.format == null )
+        {
+            throw new IllegalArgumentException( "When an input directory is given, an explicit input format must be "
+                    + "selected to filter for the relevant files" );
+        }
     }
 
     /**
@@ -63,25 +81,28 @@ public class InputFileWrapper
      * @throws FileNotFoundException if the file for absolutePath is not found.
      * @see #valueOf(String, String, String, String[]) using AUTO_FORMAT
      */
-    public static InputFileWrapper valueOf( String absolutePath, String format, String[] supportedFormat )
+    public static InputFileWrapper valueOf( String absolutePath, String format )
         throws UnsupportedEncodingException, FileNotFoundException
     {
-        return valueOf( absolutePath, format, AUTO_FORMAT, supportedFormat );
+        return valueOf( absolutePath, format, WriterFactory.UTF_8 );
     }
 
     /**
      * @param absolutePath for a wanted file or a wanted directory, not null.
      * @param format could be null
      * @param charsetName could be null
-     * @param supportedFormat not null
      * @return a type safe input reader
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      * @throws FileNotFoundException if the file for absolutePath is not found.
      */
-    public static InputFileWrapper valueOf( String absolutePath, String format, String charsetName,
-                                            String[] supportedFormat )
+    public static InputFileWrapper valueOf( String absolutePath, String format, String charsetName )
         throws UnsupportedEncodingException, FileNotFoundException
     {
-        return new InputFileWrapper( absolutePath, format, charsetName, supportedFormat );
+        return new InputFileWrapper( absolutePath, format, charsetName );
+    }
+
+    public DefaultConverter.ParserFormat getFormat()
+    {
+        return format;
     }
 }
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/InputReaderWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/InputReaderWrapper.java
index d74004f..b9b5763 100644
--- a/src/main/java/org/apache/maven/doxia/wrapper/InputReaderWrapper.java
+++ b/src/main/java/org/apache/maven/doxia/wrapper/InputReaderWrapper.java
@@ -21,19 +21,22 @@ package org.apache.maven.doxia.wrapper;
 
 import java.io.Reader;
 
+import org.apache.maven.doxia.DefaultConverter;
+
 /**
  * Wrapper for an input reader.
  *
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  */
 public class InputReaderWrapper
-    extends AbstractWrapper
 {
     /** serialVersionUID */
     static final long serialVersionUID = 3260213754615748766L;
 
     private final Reader reader;
 
+    private final DefaultConverter.ParserFormat format;
+
     /**
      * Private constructor.
      *
@@ -41,14 +44,9 @@ public class InputReaderWrapper
      * @param supportedFormat not null
      * @throws IllegalArgumentException if the format equals AUTO_FORMAT.
      */
-    private InputReaderWrapper( Reader reader, String format, String[] supportedFormat )
+    private InputReaderWrapper( Reader reader, String format )
     {
-        super( format, supportedFormat );
-
-        if ( getFormat().equalsIgnoreCase( AUTO_FORMAT ) )
-        {
-            throw new IllegalArgumentException( "input format is required" );
-        }
+        this.format = DefaultConverter.ParserFormat.valueOf( format.toUpperCase() );
 
         if ( reader == null )
         {
@@ -65,14 +63,17 @@ public class InputReaderWrapper
         return this.reader;
     }
 
+    public DefaultConverter.ParserFormat getFormat()
+    {
+        return format;
+    }
     /**
      * @param reader not null
      * @param format not null
-     * @param supportedFormat not null
      * @return a type safe input reader
      */
-    public static InputReaderWrapper valueOf( Reader reader, String format, String[] supportedFormat )
+    public static InputReaderWrapper valueOf( Reader reader, String format )
     {
-        return new InputReaderWrapper( reader, format, supportedFormat );
+        return new InputReaderWrapper( reader, format );
     }
 }
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/OutputFileWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/OutputFileWrapper.java
index a90a1e1..b0fdee9 100644
--- a/src/main/java/org/apache/maven/doxia/wrapper/OutputFileWrapper.java
+++ b/src/main/java/org/apache/maven/doxia/wrapper/OutputFileWrapper.java
@@ -21,6 +21,7 @@ package org.apache.maven.doxia.wrapper;
 
 import java.io.UnsupportedEncodingException;
 
+import org.apache.maven.doxia.DefaultConverter;
 import org.codehaus.plexus.util.WriterFactory;
 
 import static org.codehaus.plexus.util.StringUtils.isEmpty;
@@ -36,6 +37,8 @@ public class OutputFileWrapper
     /** serialVersionUID */
     static final long serialVersionUID = 804499615902780116L;
 
+    private final DefaultConverter.SinkFormat format;
+
     /**
      * Private constructor.
      *
@@ -46,15 +49,17 @@ public class OutputFileWrapper
      * @throws IllegalArgumentException if any.
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      */
-    private OutputFileWrapper( String absolutePath, String format, String charsetName, String[] supportedFormat )
+    private OutputFileWrapper( String absolutePath, String format, String charsetName )
         throws UnsupportedEncodingException
     {
-        super( absolutePath, format, charsetName, supportedFormat );
+        super( absolutePath, charsetName );
 
-        if ( getFormat().equalsIgnoreCase( AUTO_FORMAT ) )
-        {
-            throw new IllegalArgumentException( "output format could not be " + AUTO_FORMAT );
-        }
+        this.format = DefaultConverter.SinkFormat.valueOf( format.toUpperCase() );
+    }
+
+    public DefaultConverter.SinkFormat getFormat()
+    {
+        return format;
     }
 
     /**
@@ -64,10 +69,10 @@ public class OutputFileWrapper
      * @return a type safe output writer
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      */
-    public static OutputFileWrapper valueOf( String absolutePath, String format, String[] supportedFormat )
+    public static OutputFileWrapper valueOf( String absolutePath, String format )
         throws UnsupportedEncodingException
     {
-        return valueOf( absolutePath, format, WriterFactory.UTF_8, supportedFormat );
+        return valueOf( absolutePath, format, WriterFactory.UTF_8 );
     }
 
     /**
@@ -78,14 +83,13 @@ public class OutputFileWrapper
      * @return a type safe output writer
      * @throws UnsupportedEncodingException if the encoding is unsupported.
      */
-    public static OutputFileWrapper valueOf( String absolutePath, String format, String charsetName,
-                                             String[] supportedFormat )
+    public static OutputFileWrapper valueOf( String absolutePath, String format, String charsetName )
         throws UnsupportedEncodingException
     {
         if ( isEmpty( format ) )
         {
             throw new IllegalArgumentException( "output format is required" );
         }
-        return new OutputFileWrapper( absolutePath, format, charsetName, supportedFormat );
+        return new OutputFileWrapper( absolutePath, format, charsetName );
     }
 }
diff --git a/src/main/java/org/apache/maven/doxia/wrapper/OutputStreamWrapper.java b/src/main/java/org/apache/maven/doxia/wrapper/OutputStreamWrapper.java
index 2357504..bff3a7a 100644
--- a/src/main/java/org/apache/maven/doxia/wrapper/OutputStreamWrapper.java
+++ b/src/main/java/org/apache/maven/doxia/wrapper/OutputStreamWrapper.java
@@ -22,6 +22,8 @@ package org.apache.maven.doxia.wrapper;
 import java.io.OutputStream;
 import java.util.Objects;
 
+import org.apache.maven.doxia.DefaultConverter;
+
 import static org.codehaus.plexus.util.StringUtils.isEmpty;
 
 /**
@@ -30,7 +32,6 @@ import static org.codehaus.plexus.util.StringUtils.isEmpty;
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  */
 public class OutputStreamWrapper
-    extends AbstractWrapper
 {
     /** serialVersionUID */
     static final long serialVersionUID = 3329037527245430610L;
@@ -39,6 +40,8 @@ public class OutputStreamWrapper
 
     private final String encoding;
 
+    private final DefaultConverter.SinkFormat format;
+
     /**
      * Private constructor.
      *
@@ -46,19 +49,18 @@ public class OutputStreamWrapper
      * @param supportedFormat not null
      * @throws IllegalArgumentException if any.
      */
-    private OutputStreamWrapper( OutputStream out, String format, String encoding, String[] supportedFormat )
+    private OutputStreamWrapper( OutputStream out, String format, String encoding )
     {
-        super( format, supportedFormat );
-
-        if ( getFormat().equalsIgnoreCase( AUTO_FORMAT ) )
-        {
-            throw new IllegalArgumentException( "output format is required" );
-        }
-
+        this.format = DefaultConverter.SinkFormat.valueOf( format.toUpperCase() );
         this.out = out;
         this.encoding = encoding;
     }
 
+    public DefaultConverter.SinkFormat getFormat()
+    {
+        return format;
+    }
+
     /**
      * @return the output stream
      */
@@ -79,11 +81,9 @@ public class OutputStreamWrapper
      * @param out not null
      * @param format not null
      * @param encoding not null
-     * @param supportedFormat not null
      * @return a type safe output stream wrapper
      */
-    public static OutputStreamWrapper valueOf( OutputStream out, String format, String encoding,
-            String[] supportedFormat )
+    public static OutputStreamWrapper valueOf( OutputStream out, String format, String encoding )
     {
         Objects.requireNonNull( out, "output writer is required" );
         if ( isEmpty( format ) )
@@ -91,6 +91,6 @@ public class OutputStreamWrapper
             throw new IllegalArgumentException( "output format is required" );
         }
 
-        return new OutputStreamWrapper( out, format, encoding, supportedFormat );
+        return new OutputStreamWrapper( out, format, encoding );
     }
 }
diff --git a/src/test/java/org/apache/maven/doxia/ConverterTest.java b/src/test/java/org/apache/maven/doxia/ConverterTest.java
index fc380f0..463d182 100644
--- a/src/test/java/org/apache/maven/doxia/ConverterTest.java
+++ b/src/test/java/org/apache/maven/doxia/ConverterTest.java
@@ -27,6 +27,7 @@ import java.io.FileWriter;
 import java.io.OutputStream;
 import java.io.StringWriter;
 
+import org.apache.maven.doxia.DefaultConverter.ParserFormat;
 import org.apache.maven.doxia.wrapper.InputFileWrapper;
 import org.apache.maven.doxia.wrapper.InputReaderWrapper;
 import org.apache.maven.doxia.wrapper.OutputFileWrapper;
@@ -72,19 +73,30 @@ public class ConverterTest
     }
 
     /**
-     * @see Converter#getInputFormats()
+     * Input file / output dir
+     *
+     * @see Converter#convert(InputFileWrapper, OutputFileWrapper)
+     * @throws Exception if any
      */
-    public void testGetInputFormats()
+    public void testFileConverterWithInputFileOutputDir()
+        throws Exception
     {
-        assertNotNull( converter.getInputFormats() );
-    }
+        String in = getBasedir() + "/src/test/resources/unit/Doxia.htm";
+        String from = "xhtml";
+        String out = getBasedir() + "/target/unit/";
+        String to = "apt";
 
-    /**
-     * @see Converter#getOutputFormats()
-     */
-    public void testGetOutputFormats()
-    {
-        assertNotNull( converter.getOutputFormats() );
+        InputFileWrapper input =
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        OutputFileWrapper output =
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
+
+        converter.setFormatOutput( formatOutput );
+        converter.convert( input, output );
+        assertTrue( new File( out, "Doxia.apt" ).exists() );
+        assertTrue( new File( out, "Doxia.apt" ).length() != 0 );
+
+        FileUtils.deleteDirectory( new File( getBasedir() + "/target/unit/" ) );
     }
 
     /**
@@ -93,23 +105,25 @@ public class ConverterTest
      * @see Converter#convert(InputFileWrapper, OutputFileWrapper)
      * @throws Exception if any
      */
-    public void testFileConverterWithInputFileOutputDir()
+    public void testFileConverterWithInputDirOutputDir()
         throws Exception
     {
-        String in = getBasedir() + "/src/test/resources/unit/Doxia.htm";
-        String from = "xhtml";
+        String in = getBasedir() + "/src/test/resources/unit/apt";
+        String from = "apt";
         String out = getBasedir() + "/target/unit/";
-        String to = "apt";
+        String to = "markdown";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
-        assertTrue( new File( out, "Doxia.htm.apt" ).exists() );
-        assertTrue( new File( out, "Doxia.htm.apt" ).length() != 0 );
+        assertTrue( new File( out, "test.md" ).exists() );
+        assertTrue( new File( out, "test.md" ).length() != 0 );
+        assertTrue( new File( out, "child/test.md" ).exists() );
+        assertTrue( new File( out, "child/test.md" ).length() != 0 );
 
         FileUtils.deleteDirectory( new File( getBasedir() + "/target/unit/" ) );
     }
@@ -129,9 +143,9 @@ public class ConverterTest
         String to = "apt";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -156,9 +170,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -170,8 +184,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/apt/test.apt";
         to = "apt";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -194,9 +208,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -208,8 +222,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/confluence/test.confluence";
         to = "confluence";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -230,9 +244,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -244,8 +258,8 @@ public class ConverterTest
          out = getBasedir() + "/target/unit/file/docbook/test.docbook";
          to = "docbook";
 
-         input = InputFileWrapper.valueOf( in, from, converter.getInputFormats() );
-         output = OutputFileWrapper.valueOf( out, to, converter.getOutputFormats() );
+         input = InputFileWrapper.valueOf( in, from );
+         output = OutputFileWrapper.valueOf( out, to );
 
          converter.setFormatOutput( formatOutput );
          converter.convert( input, output );
@@ -267,9 +281,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -283,15 +297,15 @@ public class ConverterTest
 
         try
         {
-            input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-            output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+            output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
 
             fail();
         }
-        catch ( UnsupportedFormatException e )
+        catch ( IllegalArgumentException e )
         {
             assertTrue( true );
         }
@@ -312,9 +326,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -326,8 +340,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/twiki/test.twiki";
         to = "twiki";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         try
@@ -359,9 +373,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -373,8 +387,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/xdoc/test.xdoc";
         to = "xdoc";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -397,9 +411,9 @@ public class ConverterTest
         String to = "xhtml";
 
         InputFileWrapper input =
-            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+            InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+            OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -411,8 +425,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/xhtml/test.xhtml";
         to = "xhtml";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -434,9 +448,9 @@ public class ConverterTest
         String to = "xhtml5";
 
         InputFileWrapper input =
-                InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
+                InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
         OutputFileWrapper output =
-                OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+                OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -448,8 +462,8 @@ public class ConverterTest
         out = getBasedir() + "/target/unit/file/xhtml/test.xhtml5";
         to = "xhtml5";
 
-        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8, converter.getInputFormats() );
-        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8, converter.getOutputFormats() );
+        input = InputFileWrapper.valueOf( in, from, ReaderFactory.UTF_8 );
+        output = OutputFileWrapper.valueOf( out, to, WriterFactory.UTF_8 );
 
         converter.setFormatOutput( formatOutput );
         converter.convert( input, output );
@@ -479,10 +493,8 @@ public class ConverterTest
         {
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-            InputReaderWrapper input = InputReaderWrapper.valueOf( new FileReader( inFile ), from,
-                    converter.getInputFormats() );
-            OutputStreamWrapper output = OutputStreamWrapper.valueOf( outputStream, to, "UTF-8",
-                    converter.getOutputFormats() );
+            InputReaderWrapper input = InputReaderWrapper.valueOf( new FileReader( inFile ), from );
+            OutputStreamWrapper output = OutputStreamWrapper.valueOf( outputStream, to, "UTF-8" );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -516,10 +528,8 @@ public class ConverterTest
         {
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 
-            InputReaderWrapper input = InputReaderWrapper.valueOf( new FileReader( inFile ), from,
-                    converter.getInputFormats() );
-            OutputStreamWrapper output = OutputStreamWrapper.valueOf( outputStream, to, "UTF-8",
-                    converter.getOutputFormats() );
+            InputReaderWrapper input = InputReaderWrapper.valueOf( new FileReader( inFile ), from );
+            OutputStreamWrapper output = OutputStreamWrapper.valueOf( outputStream, to, "UTF-8" );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -553,9 +563,9 @@ public class ConverterTest
             StringWriter writer = new StringWriter();
 
             InputFileWrapper input =
-                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null, converter.getInputFormats() );
+                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null );
             OutputFileWrapper output =
-                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to, converter.getOutputFormats() );
+                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -579,9 +589,9 @@ public class ConverterTest
             StringWriter writer = new StringWriter();
 
             InputFileWrapper input =
-                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null, converter.getInputFormats() );
+                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null );
             OutputFileWrapper output =
-                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to, converter.getOutputFormats() );
+                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -603,9 +613,9 @@ public class ConverterTest
         try (FileWriter fw = new FileWriter( outFile ))
         {
             InputFileWrapper input =
-                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null, converter.getInputFormats() );
+                InputFileWrapper.valueOf( inFile.getAbsolutePath(), null );
             OutputFileWrapper output =
-                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to, converter.getOutputFormats() );
+                OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -630,9 +640,9 @@ public class ConverterTest
             StringWriter writer = new StringWriter();
 
             InputFileWrapper input =
-                    InputFileWrapper.valueOf( inFile.getAbsolutePath(), null, converter.getInputFormats() );
+                    InputFileWrapper.valueOf( inFile.getAbsolutePath(), null );
             OutputFileWrapper output =
-                    OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to, converter.getOutputFormats() );
+                    OutputFileWrapper.valueOf( outFile.getAbsolutePath(), to );
 
             converter.setFormatOutput( formatOutput );
             converter.convert( input, output );
@@ -669,12 +679,12 @@ public class ConverterTest
         assertEquals( "UTF-8", autoDetectEncoding( "xhtml/test.xhtml" ) );
     }
 
-    private String autoDetectFormat( File f, String encoding )
+    private ParserFormat autoDetectFormat( File f, String encoding )
     {
-        return DefaultConverter.autoDetectFormat( f, encoding );
+        return DefaultConverter.ParserFormat.autoDetectFormat( f, encoding );
     }
 
-    private String autoDetectFormat( String filename, String encoding )
+    private ParserFormat autoDetectFormat( String filename, String encoding )
     {
         return autoDetectFormat( new File( getBasedir() + "/src/test/resources/unit/" + filename ), encoding );
     }
@@ -685,7 +695,7 @@ public class ConverterTest
      */
     public void testAutodetectFormat()
     {
-        assertEquals( autoDetectFormat( "apt/test.apt", "UTF-8" ), "apt" );
+        assertEquals( autoDetectFormat( "apt/test.apt", "UTF-8" ), ParserFormat.APT );
 
         try
         {
@@ -697,10 +707,10 @@ public class ConverterTest
             assertTrue( true );
         }
 
-        assertEquals( autoDetectFormat( "confluence/test.confluence", "UTF-8" ), "confluence" );
-        assertEquals( autoDetectFormat( "docbook/test.xml", "UTF-8" ), "docbook" );
-        assertEquals( autoDetectFormat( "fml/test.fml", "UTF-8" ), "fml" );
-        assertEquals( autoDetectFormat( "twiki/test.twiki", "UTF-8" ), "twiki" );
-        assertEquals( autoDetectFormat( "xhtml/test.xhtml", "UTF-8" ), "xhtml" );
+        assertEquals( autoDetectFormat( "confluence/test.confluence", "UTF-8" ), ParserFormat.CONFLUENCE );
+        assertEquals( autoDetectFormat( "docbook/test.xml", "UTF-8" ), ParserFormat.DOCBOOK );
+        assertEquals( autoDetectFormat( "fml/test.fml", "UTF-8" ), ParserFormat.FML );
+        assertEquals( autoDetectFormat( "twiki/test.twiki", "UTF-8" ), ParserFormat.TWIKI );
+        assertEquals( autoDetectFormat( "xhtml/test.xhtml", "UTF-8" ), ParserFormat.XHTML );
     }
 }
diff --git a/src/test/resources/unit/apt/child/test.apt b/src/test/resources/unit/apt/child/test.apt
new file mode 100644
index 0000000..7f84c9f
--- /dev/null
+++ b/src/test/resources/unit/apt/child/test.apt
@@ -0,0 +1 @@
+Section title
\ No newline at end of file