package org.apache.maven.archetype.creator;

/*
 * 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.commons.collections.CollectionUtils;
import org.apache.maven.archetype.ArchetypeCreationRequest;
import org.apache.maven.archetype.ArchetypeCreationResult;
import org.apache.maven.archetype.common.ArchetypeFilesResolver;
import org.apache.maven.archetype.common.Constants;
import org.apache.maven.archetype.common.PomManager;
import org.apache.maven.archetype.common.util.FileCharsetDetector;
import org.apache.maven.archetype.common.util.ListScanner;
import org.apache.maven.archetype.common.util.PathUtils;
import org.apache.maven.archetype.exception.TemplateCreationException;
import org.apache.maven.archetype.metadata.ArchetypeDescriptor;
import org.apache.maven.archetype.metadata.FileSet;
import org.apache.maven.archetype.metadata.ModuleDescriptor;
import org.apache.maven.archetype.metadata.RequiredProperty;
import org.apache.maven.archetype.metadata.io.xpp3.ArchetypeDescriptorXpp3Writer;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Extension;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Profile;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
import org.apache.maven.shared.invoker.DefaultInvoker;
import org.apache.maven.shared.invoker.InvocationRequest;
import org.apache.maven.shared.invoker.Invoker;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Create a 2.x Archetype project from a project. Since 2.0-alpha-5, an integration-test named "basic" is created along
 * the archetype itself to provide immediate test when building the archetype.
 */
@Component( role = ArchetypeCreator.class, hint = "fileset" )
public class FilesetArchetypeCreator
    extends AbstractLogEnabled
    implements ArchetypeCreator
{
    private static final String DEFAULT_OUTPUT_DIRECTORY =
        "target" + File.separator + "generated-sources" + File.separator + "archetype";

    @Requirement
    private ArchetypeFilesResolver archetypeFilesResolver;

    @Requirement
    private PomManager pomManager;

    @Requirement
    private MavenProjectBuilder projectBuilder;

    public void createArchetype( ArchetypeCreationRequest request, ArchetypeCreationResult result )
    {
        MavenProject project = request.getProject();
        List<String> languages = request.getLanguages();
        List<String> filtereds = request.getFiltereds();
        String defaultEncoding = request.getDefaultEncoding();
        boolean preserveCData = request.isPreserveCData();
        boolean keepParent = request.isKeepParent();
        boolean partialArchetype = request.isPartialArchetype();
        ArtifactRepository localRepository = request.getLocalRepository();
        File outputDirectory = request.getOutputDirectory();
        File basedir = project.getBasedir();

        Properties properties = new Properties();
        Properties configurationProperties = new Properties();
        if ( request.getProperties() != null )
        {
            properties.putAll( request.getProperties() );
            configurationProperties.putAll( request.getProperties() );
        }

        extractPropertiesFromProject( project, properties, configurationProperties, request.getPackageName() );

        if ( outputDirectory == null )
        {
            getLogger().debug( "No output directory defined, using default: " + DEFAULT_OUTPUT_DIRECTORY );
            outputDirectory = FileUtils.resolveFile( basedir, DEFAULT_OUTPUT_DIRECTORY );
        }
        outputDirectory.mkdirs();

        getLogger().debug( "Creating archetype in " + outputDirectory );

        try
        {
            File archetypePomFile =
                createArchetypeProjectPom( project, localRepository, configurationProperties, outputDirectory );

            File archetypeResourcesDirectory = new File( outputDirectory, getTemplateOutputDirectory() );

            File archetypeFilesDirectory = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_RESOURCES );
            getLogger().debug( "Archetype's files output directory " + archetypeFilesDirectory );

            File archetypeDescriptorFile = new File( archetypeResourcesDirectory, Constants.ARCHETYPE_DESCRIPTOR );
            archetypeDescriptorFile.getParentFile().mkdirs();

            File archetypePostGenerationScript =
                new File( archetypeResourcesDirectory, Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
            archetypePostGenerationScript.getParentFile().mkdirs();

            if ( request.getProject().getBuild() != null && CollectionUtils.isNotEmpty(
                request.getProject().getBuild().getResources() ) )
            {
                File inputFile = new File(
                    request.getProject().getBuild().getResources().get( 0 ).getDirectory() + File.separator
                        + Constants.ARCHETYPE_POST_GENERATION_SCRIPT );
                if ( inputFile.exists() )
                {
                    FileUtils.copyFile( inputFile, archetypePostGenerationScript );
                }
            }

            getLogger().debug( "Starting archetype's descriptor " + project.getArtifactId() );
            ArchetypeDescriptor archetypeDescriptor = new ArchetypeDescriptor();

            archetypeDescriptor.setName( project.getArtifactId() );
            archetypeDescriptor.setPartial( partialArchetype );

            addRequiredProperties( archetypeDescriptor, properties );

            // TODO ensure reverseProperties contains NO dotted properties
            Properties reverseProperties = getReversedProperties( archetypeDescriptor, properties );
            // reverseProperties.remove( Constants.GROUP_ID );

            // TODO ensure pomReversedProperties contains NO dotted properties
            Properties pomReversedProperties = getReversedProperties( archetypeDescriptor, properties );
            // pomReversedProperties.remove( Constants.PACKAGE );

            String packageName = configurationProperties.getProperty( Constants.PACKAGE );

            Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );

            List<String> excludePatterns =
                configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
                    ? Arrays.asList(
                    StringUtils.split( configurationProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
                    : Collections.<String>emptyList();

            List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );
            if ( getLogger().isDebugEnabled() )
            {
                getLogger().debug( "Scanned for files " + fileNames.size() );

                for ( String name : fileNames )
                {
                    getLogger().debug( "- " + name );
                }
            }

            List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
            getLogger().debug( "Resolved filesets for " + archetypeDescriptor.getName() );

            archetypeDescriptor.setFileSets( filesets );

            createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
                                  defaultEncoding );
            getLogger().debug( "Created files for " + archetypeDescriptor.getName() );

            setParentArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );

            for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
            {
                String moduleId = (String) modules.next();
                String rootArtifactId = configurationProperties.getProperty( Constants.ARTIFACT_ID );
                String moduleIdDirectory = moduleId;

                if ( moduleId.indexOf( rootArtifactId ) >= 0 )
                {
                    moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
                }

                getLogger().debug( "Creating module " + moduleId );

                ModuleDescriptor moduleDescriptor =
                    createModule( reverseProperties, rootArtifactId, moduleId, packageName,
                                  FileUtils.resolveFile( basedir, moduleId ),
                                  new File( archetypeFilesDirectory, moduleIdDirectory ), languages, filtereds,
                                  defaultEncoding, preserveCData, keepParent );

                archetypeDescriptor.addModule( moduleDescriptor );

                getLogger().debug(
                    "Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
            }

            restoreParentArtifactId( reverseProperties, null );
            restoreArtifactId( reverseProperties, configurationProperties.getProperty( Constants.ARTIFACT_ID ) );

            createPoms( pom, configurationProperties.getProperty( Constants.ARTIFACT_ID ),
                        configurationProperties.getProperty( Constants.ARTIFACT_ID ), archetypeFilesDirectory, basedir,
                        pomReversedProperties, preserveCData, keepParent );
            getLogger().debug( "Created Archetype " + archetypeDescriptor.getName() + " template pom(s)" );

            Writer out = null;
            try
            {
                out = WriterFactory.newXmlWriter( archetypeDescriptorFile );

                ArchetypeDescriptorXpp3Writer writer = new ArchetypeDescriptorXpp3Writer();

                writer.write( out, archetypeDescriptor );

                getLogger().debug( "Archetype " + archetypeDescriptor.getName() + " descriptor written" );
            }
            finally
            {
                IOUtil.close( out );
            }

            createArchetypeBasicIt( archetypeDescriptor, outputDirectory );

            InvocationRequest internalRequest = new DefaultInvocationRequest();
            internalRequest.setPomFile( archetypePomFile );
            internalRequest.setGoals( Collections.singletonList( request.getPostPhase() ) );

            Invoker invoker = new DefaultInvoker();
            invoker.execute( internalRequest );
        }
        catch ( Exception e )
        {
            result.setCause( e );
        }
    }

    /**
     * Create an archetype IT, ie goals.txt and archetype.properties in src/test/resources/projects/basic.
     *
     * @param archetypeDescriptor
     * @param generatedSourcesDirectory
     * @throws IOException
     * @since 2.0-alpha-5
     */
    private void createArchetypeBasicIt( ArchetypeDescriptor archetypeDescriptor, File generatedSourcesDirectory )
        throws IOException
    {
        String basic =
            Constants.SRC + File.separator + Constants.TEST + File.separator + Constants.RESOURCES + File.separator
                + "projects" + File.separator + "basic";
        File basicItDirectory = new File( generatedSourcesDirectory, basic );
        basicItDirectory.mkdirs();

        InputStream in = null;
        OutputStream out = null;

        try
        {
            in = FilesetArchetypeCreator.class.getResourceAsStream( "archetype.properties" );

            Properties archetypeProperties = new Properties();
            archetypeProperties.load( in );

            for ( RequiredProperty req : archetypeDescriptor.getRequiredProperties() )
            {
                archetypeProperties.put( req.getKey(), req.getDefaultValue() );
            }

            out = new FileOutputStream( new File( basicItDirectory, "archetype.properties" ) );
            archetypeProperties.store( out, null );
        }
        finally
        {
            IOUtil.close( in );
            IOUtil.close( out );
        }
        copyResource( "goal.txt", new File( basicItDirectory, "goal.txt" ) );

        getLogger().debug( "Added basic integration test" );
    }

    private void extractPropertiesFromProject( MavenProject project, Properties properties,
                                               Properties configurationProperties, String packageName )
    {
        if ( !properties.containsKey( Constants.GROUP_ID ) )
        {
            properties.setProperty( Constants.GROUP_ID, project.getGroupId() );
        }
        configurationProperties.setProperty( Constants.GROUP_ID, properties.getProperty( Constants.GROUP_ID ) );

        if ( !properties.containsKey( Constants.ARTIFACT_ID ) )
        {
            properties.setProperty( Constants.ARTIFACT_ID, project.getArtifactId() );
        }
        configurationProperties.setProperty( Constants.ARTIFACT_ID, properties.getProperty( Constants.ARTIFACT_ID ) );

        if ( !properties.containsKey( Constants.VERSION ) )
        {
            properties.setProperty( Constants.VERSION, project.getVersion() );
        }
        configurationProperties.setProperty( Constants.VERSION, properties.getProperty( Constants.VERSION ) );

        if ( packageName != null )
        {
            properties.setProperty( Constants.PACKAGE, packageName );
        }
        else if ( !properties.containsKey( Constants.PACKAGE ) )
        {
            properties.setProperty( Constants.PACKAGE, project.getGroupId() );
        }
        configurationProperties.setProperty( Constants.PACKAGE, properties.getProperty( Constants.PACKAGE ) );
    }

    /**
     * Create the archetype project pom.xml file, that will be used to build the archetype.
     */
    private File createArchetypeProjectPom( MavenProject project, ArtifactRepository localRepository,
                                            Properties configurationProperties, File projectDir )
        throws TemplateCreationException, IOException
    {
        Model model = new Model();
        model.setModelVersion( "4.0.0" );
        // these values should be retrieved from the request with sensible defaults
        model.setGroupId( configurationProperties.getProperty( Constants.ARCHETYPE_GROUP_ID, project.getGroupId() ) );
        model.setArtifactId(
            configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
        model.setVersion( configurationProperties.getProperty( Constants.ARCHETYPE_VERSION, project.getVersion() ) );
        model.setPackaging( "maven-archetype" );
        model.setName(
            configurationProperties.getProperty( Constants.ARCHETYPE_ARTIFACT_ID, project.getArtifactId() ) );
        model.setUrl( configurationProperties.getProperty( Constants.ARCHETYPE_URL, project.getUrl() ) );
        model.setDescription(
            configurationProperties.getProperty( Constants.ARCHETYPE_DESCRIPTION, project.getDescription() ) );
        model.setLicenses( project.getLicenses() );
        model.setDevelopers( project.getDevelopers() );
        model.setScm( project.getScm() );
        Build build = new Build();
        model.setBuild( build );

        // In many cases where we are behind a firewall making Archetypes for work mates we want
        // to simply be able to deploy the archetypes once we have created them. In order to do
        // this we want to utilize information from the project we are creating the archetype from.
        // This will be a fully working project that has been testing and inherits from a POM
        // that contains deployment information, along with any extensions required for deployment.
        // We don't want to create archetypes that cannot be deployed after we create them. People
        // might want to edit the archetype POM but they should not have too.

        if ( project.getParent() != null )
        {
            Artifact pa = project.getParentArtifact();

            try
            {
                MavenProject p =
                    projectBuilder.buildFromRepository( pa, project.getRemoteArtifactRepositories(), localRepository );

                if ( p.getDistributionManagement() != null )
                {
                    model.setDistributionManagement( p.getDistributionManagement() );
                }

                if ( p.getBuildExtensions() != null )
                {
                    for ( Iterator<Extension> i = p.getBuildExtensions().iterator(); i.hasNext(); )
                    {
                        Extension be = i.next();

                        model.getBuild().addExtension( be );
                    }
                }
            }
            catch ( ProjectBuildingException e )
            {
                throw new TemplateCreationException(
                    "Error reading parent POM of project: " + pa.getGroupId() + ":" + pa.getArtifactId() + ":"
                        + pa.getVersion() );
            }
        }

        Extension extension = new Extension();
        extension.setGroupId( "org.apache.maven.archetype" );
        extension.setArtifactId( "archetype-packaging" );
        extension.setVersion( getArchetypeVersion() );
        model.getBuild().addExtension( extension );

        Plugin plugin = new Plugin();
        plugin.setGroupId( "org.apache.maven.plugins" );
        plugin.setArtifactId( "maven-archetype-plugin" );
        plugin.setVersion( getArchetypeVersion() );

        PluginManagement pluginManagement = new PluginManagement();
        pluginManagement.addPlugin( plugin );
        model.getBuild().setPluginManagement( pluginManagement );

        getLogger().debug( "Creating archetype's pom" );

        File archetypePomFile = new File( projectDir, Constants.ARCHETYPE_POM );

        archetypePomFile.getParentFile().mkdirs();

        copyResource( "pom-prototype.xml", archetypePomFile );

        pomManager.writePom( model, archetypePomFile, archetypePomFile );

        return archetypePomFile;
    }

    private void copyResource( String name, File destination )
        throws IOException
    {
        InputStream in = null;
        OutputStream out = null;

        try
        {
            in = FilesetArchetypeCreator.class.getResourceAsStream( name );
            out = new FileOutputStream( destination );

            IOUtil.copy( in, out );
        }
        finally
        {
            IOUtil.close( in );
            IOUtil.close( out );
        }
    }

    private void addRequiredProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
    {
        Properties requiredProperties = new Properties();
        requiredProperties.putAll( properties );
        requiredProperties.remove( Constants.ARCHETYPE_GROUP_ID );
        requiredProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
        requiredProperties.remove( Constants.ARCHETYPE_VERSION );
        requiredProperties.remove( Constants.GROUP_ID );
        requiredProperties.remove( Constants.ARTIFACT_ID );
        requiredProperties.remove( Constants.VERSION );
        requiredProperties.remove( Constants.PACKAGE );

        for ( Iterator<?> propertiesIterator = requiredProperties.keySet().iterator(); propertiesIterator.hasNext(); )
        {
            String propertyKey = (String) propertiesIterator.next();

            RequiredProperty requiredProperty = new RequiredProperty();
            requiredProperty.setKey( propertyKey );
            requiredProperty.setDefaultValue( requiredProperties.getProperty( propertyKey ) );

            archetypeDescriptor.addRequiredProperty( requiredProperty );

            getLogger().debug(
                "Adding requiredProperty " + propertyKey + "=" + requiredProperties.getProperty( propertyKey )
                    + " to archetype's descriptor" );
        }
    }

    private void createModulePoms( Properties pomReversedProperties, String rootArtifactId, String packageName,
                                   File basedir, File archetypeFilesDirectory, boolean preserveCData,
                                   boolean keepParent )
        throws FileNotFoundException, IOException, XmlPullParserException
    {
        Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );

        String parentArtifactId = pomReversedProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
        String artifactId = pom.getArtifactId();
        setParentArtifactId( pomReversedProperties, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ) );
        setArtifactId( pomReversedProperties, pom.getArtifactId() );

        for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
        {
            String subModuleId = modules.next();

            String subModuleIdDirectory = subModuleId;

            if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
            {
                subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
            }

            createModulePoms( pomReversedProperties, rootArtifactId, packageName,
                              FileUtils.resolveFile( basedir, subModuleId ),
                              FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), preserveCData,
                              keepParent );
        }

        createModulePom( pom, rootArtifactId, archetypeFilesDirectory, pomReversedProperties,
                         FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );

        restoreParentArtifactId( pomReversedProperties, parentArtifactId );
        restoreArtifactId( pomReversedProperties, artifactId );
    }

    private void createPoms( Model pom, String rootArtifactId, String artifactId, File archetypeFilesDirectory,
                             File basedir, Properties pomReversedProperties, boolean preserveCData, boolean keepParent )
        throws IOException, FileNotFoundException, XmlPullParserException
    {
        setArtifactId( pomReversedProperties, pom.getArtifactId() );

        for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
        {
            String moduleId = modules.next();

            String moduleIdDirectory = moduleId;

            if ( moduleId.indexOf( rootArtifactId ) >= 0 )
            {
                moduleIdDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
            }

            createModulePoms( pomReversedProperties, rootArtifactId, moduleId,
                              FileUtils.resolveFile( basedir, moduleId ),
                              new File( archetypeFilesDirectory, moduleIdDirectory ), preserveCData, keepParent );
        }

        restoreParentArtifactId( pomReversedProperties, null );
        restoreArtifactId( pomReversedProperties, artifactId );

        createArchetypePom( pom, archetypeFilesDirectory, pomReversedProperties,
                            FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ), preserveCData, keepParent );
    }

    private String getPackageInPathFormat( String aPackage )
    {
        return StringUtils.replace( aPackage, ".", "/" );
    }

    private void rewriteReferences( Model pom, String rootArtifactId, String groupId )
    {
        // rewrite Dependencies
        if ( pom.getDependencies() != null && !pom.getDependencies().isEmpty() )
        {
            for ( Iterator<Dependency> dependencies = pom.getDependencies().iterator(); dependencies.hasNext(); )
            {
                rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
            }
        }

        // rewrite DependencyManagement
        if ( pom.getDependencyManagement() != null && pom.getDependencyManagement().getDependencies() != null
            && !pom.getDependencyManagement().getDependencies().isEmpty() )
        {
            for ( Iterator<Dependency> dependencies = pom.getDependencyManagement().getDependencies().iterator();
                  dependencies.hasNext(); )
            {
                rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
            }
        }

        // rewrite Plugins
        if ( pom.getBuild() != null && pom.getBuild().getPlugins() != null && !pom.getBuild().getPlugins().isEmpty() )
        {
            for ( Iterator<Plugin> plugins = pom.getBuild().getPlugins().iterator(); plugins.hasNext(); )
            {
                rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
            }
        }

        // rewrite PluginManagement
        if ( pom.getBuild() != null && pom.getBuild().getPluginManagement() != null
            && pom.getBuild().getPluginManagement().getPlugins() != null
            && !pom.getBuild().getPluginManagement().getPlugins().isEmpty() )
        {
            for ( Iterator<Plugin> plugins = pom.getBuild().getPluginManagement().getPlugins().iterator();
                  plugins.hasNext(); )
            {
                rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
            }
        }

        // rewrite Profiles
        if ( pom.getProfiles() != null )
        {
            for ( Iterator<Profile> profiles = pom.getProfiles().iterator(); profiles.hasNext(); )
            {
                Profile profile = profiles.next();

                // rewrite Dependencies
                if ( profile.getDependencies() != null && !profile.getDependencies().isEmpty() )
                {
                    for ( Iterator<Dependency> dependencies = profile.getDependencies().iterator();
                          dependencies.hasNext(); )
                    {
                        rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
                    }
                }

                // rewrite DependencyManagement
                if ( profile.getDependencyManagement() != null
                    && profile.getDependencyManagement().getDependencies() != null
                    && !profile.getDependencyManagement().getDependencies().isEmpty() )
                {
                    for ( Iterator<Dependency> dependencies =
                              profile.getDependencyManagement().getDependencies().iterator(); dependencies.hasNext(); )
                    {
                        rewriteDependencyReferences( dependencies.next(), rootArtifactId, groupId );
                    }
                }

                // rewrite Plugins
                if ( profile.getBuild() != null && profile.getBuild().getPlugins() != null
                    && !profile.getBuild().getPlugins().isEmpty() )
                {
                    for ( Iterator<Plugin> plugins = profile.getBuild().getPlugins().iterator(); plugins.hasNext(); )
                    {
                        rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
                    }
                }

                // rewrite PluginManagement
                if ( profile.getBuild() != null && profile.getBuild().getPluginManagement() != null
                    && profile.getBuild().getPluginManagement().getPlugins() != null
                    && !profile.getBuild().getPluginManagement().getPlugins().isEmpty() )
                {
                    for ( Iterator<Plugin> plugins = profile.getBuild().getPluginManagement().getPlugins().iterator();
                          plugins.hasNext(); )
                    {
                        rewritePluginReferences( plugins.next(), rootArtifactId, groupId );
                    }
                }
            }
        }
    }

    private void rewriteDependencyReferences( Dependency dependency, String rootArtifactId, String groupId )
    {
        if ( dependency.getArtifactId() != null && dependency.getArtifactId().indexOf( rootArtifactId ) >= 0 )
        {
            if ( dependency.getGroupId() != null )
            {
                dependency.setGroupId(
                    StringUtils.replace( dependency.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" ) );
            }

            dependency.setArtifactId(
                StringUtils.replace( dependency.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );

            if ( dependency.getVersion() != null )
            {
                dependency.setVersion( "${" + Constants.VERSION + "}" );
            }
        }
    }

    private void rewritePluginReferences( Plugin plugin, String rootArtifactId, String groupId )
    {
        if ( plugin.getArtifactId() != null && plugin.getArtifactId().indexOf( rootArtifactId ) >= 0 )
        {
            if ( plugin.getGroupId() != null )
            {
                String g = StringUtils.replace( plugin.getGroupId(), groupId, "${" + Constants.GROUP_ID + "}" );
                plugin.setGroupId( g );
            }

            plugin.setArtifactId( StringUtils.replace( plugin.getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );

            if ( plugin.getVersion() != null )
            {
                plugin.setVersion( "${" + Constants.VERSION + "}" );
            }
        }

        if ( plugin.getArtifactId() != null && "maven-ear-plugin".equals( plugin.getArtifactId() ) )
        {
            rewriteEARPluginReferences( plugin, rootArtifactId, groupId );
        }
    }

    private void rewriteEARPluginReferences( Plugin plugin, String rootArtifactId, String groupId )
    {
        Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
        if ( configuration != null )
        {
            Xpp3Dom[] modules = configuration.getChild( "modules" ).getChildren();
            for ( int i = 0; i < modules.length; i++ )
            {
                Xpp3Dom module = modules[i];
                Xpp3Dom moduleGroupId = module.getChild( "groupId" );
                Xpp3Dom moduleArtifactId = module.getChild( "artifactId" );
                Xpp3Dom moduleBundleFileName = module.getChild( "bundleFileName" );
                Xpp3Dom moduleModuleId = module.getChild( "moduleId" );
                Xpp3Dom moduleContextRoot = module.getChild( "contextRoot" );

                if ( moduleGroupId != null )
                {
                    moduleGroupId.setValue(
                        StringUtils.replace( moduleGroupId.getValue(), groupId, "${" + Constants.GROUP_ID + "}" ) );
                }

                if ( moduleArtifactId != null )
                {
                    moduleArtifactId.setValue(
                        StringUtils.replace( moduleArtifactId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
                }

                if ( moduleBundleFileName != null )
                {
                    moduleBundleFileName.setValue(
                        StringUtils.replace( moduleBundleFileName.getValue(), rootArtifactId, "${rootArtifactId}" ) );
                }

                if ( moduleModuleId != null )
                {
                    moduleModuleId.setValue(
                        StringUtils.replace( moduleModuleId.getValue(), rootArtifactId, "${rootArtifactId}" ) );
                }

                if ( moduleContextRoot != null )
                {
                    moduleContextRoot.setValue(
                        StringUtils.replace( moduleContextRoot.getValue(), rootArtifactId, "${rootArtifactId}" ) );
                }
            }
        }
    }

    private void setArtifactId( Properties properties, String artifactId )
    {
        properties.setProperty( Constants.ARTIFACT_ID, artifactId );
    }

    private List<String> concatenateToList( List<String> toConcatenate, String with )
    {
        List<String> result = new ArrayList<String>( toConcatenate.size() );

        for ( String concatenate : toConcatenate )
        {
            result.add( ( ( with.length() > 0 ) ? ( with + "/" + concatenate ) : concatenate ) );
        }

        return result;
    }

    private void copyFiles( File basedir, File archetypeFilesDirectory, String directory, List<String> fileSetResources,
                            boolean packaged, String packageName )
        throws IOException
    {
        String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );

        getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );

        for ( String inputFileName : fileSetResources )
        {
            String outputFileName = packaged
                ? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
                : inputFileName;
            getLogger().debug( "InputFileName:" + inputFileName );
            getLogger().debug( "OutputFileName:" + outputFileName );

            File outputFile = new File( archetypeFilesDirectory, outputFileName );

            File inputFile = new File( basedir, inputFileName );

            outputFile.getParentFile().mkdirs();

            FileUtils.copyFile( inputFile, outputFile );
        }
    }

    private void createArchetypeFiles( Properties reverseProperties, List<FileSet> fileSets, String packageName,
                                       File basedir, File archetypeFilesDirectory, String defaultEncoding )
        throws IOException
    {
        getLogger().debug( "Creating Archetype/Module files from " + basedir + " to " + archetypeFilesDirectory );

        for ( FileSet fileSet : fileSets )
        {
            DirectoryScanner scanner = new DirectoryScanner();
            scanner.setBasedir( basedir );
            scanner.setIncludes( (String[]) concatenateToList( fileSet.getIncludes(), fileSet.getDirectory() ).toArray(
                new String[fileSet.getIncludes().size()] ) );
            scanner.setExcludes( (String[]) fileSet.getExcludes().toArray( new String[fileSet.getExcludes().size()] ) );
            scanner.addDefaultExcludes();
            getLogger().debug( "Using fileset " + fileSet );
            scanner.scan();

            List<String> fileSetResources = Arrays.asList( scanner.getIncludedFiles() );
            getLogger().debug( "Scanned " + fileSetResources.size() + " resources" );

            if ( fileSet.isFiltered() )
            {
                processFileSet( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
                                fileSet.isPackaged(), packageName, reverseProperties, defaultEncoding );
                getLogger().debug( "Processed " + fileSet.getDirectory() + " files" );
            }
            else
            {
                copyFiles( basedir, archetypeFilesDirectory, fileSet.getDirectory(), fileSetResources,
                           fileSet.isPackaged(), packageName );
                getLogger().debug( "Copied " + fileSet.getDirectory() + " files" );
            }
        }
    }

    private void createArchetypePom( Model pom, File archetypeFilesDirectory, Properties pomReversedProperties,
                                     File initialPomFile, boolean preserveCData, boolean keepParent )
        throws IOException
    {
        File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );

        if ( preserveCData )
        {
            getLogger().debug( "Preserving CDATA parts of pom" );
            File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );

            FileUtils.copyFile( initialPomFile, inputFile );

            Reader in = null;
            Writer out = null;
            try
            {
                in = ReaderFactory.newXmlReader( inputFile );

                String initialcontent = IOUtil.toString( in );

                String content = getReversedContent( initialcontent, pomReversedProperties );

                outputFile.getParentFile().mkdirs();

                out = WriterFactory.newXmlWriter( outputFile );

                IOUtil.copy( content, out );
            }
            finally
            {
                IOUtil.close( in );
                IOUtil.close( out );
            }

            inputFile.delete();
        }
        else
        {
            if ( !keepParent )
            {
                pom.setParent( null );
            }

            pom.setModules( null );
            pom.setGroupId( "${" + Constants.GROUP_ID + "}" );
            pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );
            pom.setVersion( "${" + Constants.VERSION + "}" );
            pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
            pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
            pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );


            rewriteReferences( pom, pomReversedProperties.getProperty( Constants.ARTIFACT_ID ),
                               pomReversedProperties.getProperty( Constants.GROUP_ID ) );

            pomManager.writePom( pom, outputFile, initialPomFile );
        }

        Reader in = null;
        try
        {
            in = ReaderFactory.newXmlReader( initialPomFile );
            String initialcontent = IOUtil.toString( in );

            Iterator<?> properties = pomReversedProperties.keySet().iterator();
            while ( properties.hasNext() )
            {
                String property = (String) properties.next();

                if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
                {
                    getLogger().warn(
                        "Archetype uses ${" + property + "} for internal processing, but file " + initialPomFile
                            + " contains this property already" );
                }
            }
        }
        finally
        {
            IOUtil.close( in );
        }
    }

    private FileSet createFileSet( final List<String> excludes, final boolean packaged, final boolean filtered,
                                   final String group, final List<String> includes, String defaultEncoding )
    {
        FileSet fileSet = new FileSet();

        fileSet.setDirectory( group );
        fileSet.setPackaged( packaged );
        fileSet.setFiltered( filtered );
        fileSet.setIncludes( includes );
        fileSet.setExcludes( excludes );
        fileSet.setEncoding( defaultEncoding );

        getLogger().debug( "Created Fileset " + fileSet );

        return fileSet;
    }

    private List<FileSet> createFileSets( List<String> files, int level, boolean packaged, String packageName,
                                          boolean filtered, String defaultEncoding )
    {
        List<FileSet> fileSets = new ArrayList<FileSet>();

        if ( !files.isEmpty() )
        {
            getLogger().debug( "Creating filesets" + ( packaged ? ( " packaged (" + packageName + ")" ) : "" ) + (
                filtered
                    ? " filtered"
                    : "" ) + " at level " + level );
            if ( level == 0 )
            {
                List<String> includes = new ArrayList<String>( files );
                List<String> excludes = new ArrayList<String>();

                if ( !includes.isEmpty() )
                {
                    fileSets.add( createFileSet( excludes, packaged, filtered, "", includes, defaultEncoding ) );
                }
            }
            else
            {
                Map<String, List<String>> groups = getGroupsMap( files, level );

                for ( String group : groups.keySet() )
                {
                    getLogger().debug( "Creating filesets for group " + group );

                    if ( !packaged )
                    {
                        fileSets.add( getUnpackagedFileSet( filtered, group, groups.get( group ), defaultEncoding ) );
                    }
                    else
                    {
                        fileSets.addAll(
                            getPackagedFileSets( filtered, group, groups.get( group ), packageName, defaultEncoding ) );
                    }
                }
            } // end if

            getLogger().debug( "Resolved fileSets " + fileSets );
        } // end if

        return fileSets;
    }

    private ModuleDescriptor createModule( Properties reverseProperties, String rootArtifactId, String moduleId,
                                           String packageName, File basedir, File archetypeFilesDirectory,
                                           List<String> languages, List<String> filtereds, String defaultEncoding,
                                           boolean preserveCData, boolean keepParent )
        throws IOException, XmlPullParserException
    {
        ModuleDescriptor archetypeDescriptor = new ModuleDescriptor();
        getLogger().debug( "Starting module's descriptor " + moduleId );

        archetypeFilesDirectory.mkdirs();
        getLogger().debug( "Module's files output directory " + archetypeFilesDirectory );

        Model pom = pomManager.readPom( FileUtils.resolveFile( basedir, Constants.ARCHETYPE_POM ) );
        String replacementId = pom.getArtifactId();
        String moduleDirectory = pom.getArtifactId();

        if ( replacementId.indexOf( rootArtifactId ) >= 0 )
        {
            replacementId = StringUtils.replace( replacementId, rootArtifactId, "${rootArtifactId}" );
            moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
        }

        if ( moduleId.indexOf( rootArtifactId ) >= 0 )
        {
            moduleDirectory = StringUtils.replace( moduleId, rootArtifactId, "__rootArtifactId__" );
        }

        archetypeDescriptor.setName( replacementId );
        archetypeDescriptor.setId( replacementId );
        archetypeDescriptor.setDir( moduleDirectory );

        setArtifactId( reverseProperties, pom.getArtifactId() );

        List<String> excludePatterns =
            reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ) != null
                ? Arrays.asList( StringUtils.split( reverseProperties.getProperty( Constants.EXCLUDE_PATTERNS ), "," ) )
                : Collections.<String>emptyList();

        List<String> fileNames = resolveFileNames( pom, basedir, excludePatterns );

        List<FileSet> filesets = resolveFileSets( packageName, fileNames, languages, filtereds, defaultEncoding );
        getLogger().debug( "Resolved filesets for module " + archetypeDescriptor.getName() );

        archetypeDescriptor.setFileSets( filesets );

        createArchetypeFiles( reverseProperties, filesets, packageName, basedir, archetypeFilesDirectory,
                              defaultEncoding );
        getLogger().debug( "Created files for module " + archetypeDescriptor.getName() );

        String parentArtifactId = reverseProperties.getProperty( Constants.PARENT_ARTIFACT_ID );
        setParentArtifactId( reverseProperties, pom.getArtifactId() );

        for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
        {
            String subModuleId = modules.next();

            String subModuleIdDirectory = subModuleId;
            if ( subModuleId.indexOf( rootArtifactId ) >= 0 )
            {
                subModuleIdDirectory = StringUtils.replace( subModuleId, rootArtifactId, "__rootArtifactId__" );
            }

            getLogger().debug( "Creating module " + subModuleId );

            ModuleDescriptor moduleDescriptor =
                createModule( reverseProperties, rootArtifactId, subModuleId, packageName,
                              FileUtils.resolveFile( basedir, subModuleId ),
                              FileUtils.resolveFile( archetypeFilesDirectory, subModuleIdDirectory ), languages,
                              filtereds, defaultEncoding, preserveCData, keepParent );

            archetypeDescriptor.addModule( moduleDescriptor );

            getLogger().debug( "Added module " + moduleDescriptor.getName() + " in " + archetypeDescriptor.getName() );
        }

        restoreParentArtifactId( reverseProperties, parentArtifactId );
        restoreArtifactId( reverseProperties, pom.getArtifactId() );

        getLogger().debug( "Created Module " + archetypeDescriptor.getName() + " pom" );

        return archetypeDescriptor;
    }

    private void createModulePom( Model pom, String rootArtifactId, File archetypeFilesDirectory,
                                  Properties pomReversedProperties, File initialPomFile, boolean preserveCData,
                                  boolean keepParent )
        throws IOException
    {
        File outputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM );

        if ( preserveCData )
        {
            getLogger().debug( "Preserving CDATA parts of pom" );
            File inputFile = FileUtils.resolveFile( archetypeFilesDirectory, Constants.ARCHETYPE_POM + ".tmp" );

            FileUtils.copyFile( initialPomFile, inputFile );

            Reader in = null;
            Writer out = null;
            try
            {
                in = ReaderFactory.newXmlReader( inputFile );

                String initialcontent = IOUtil.toString( in );

                String content = getReversedContent( initialcontent, pomReversedProperties );

                outputFile.getParentFile().mkdirs();

                out = WriterFactory.newXmlWriter( outputFile );

                IOUtil.copy( content, out );
            }
            finally
            {
                IOUtil.close( in );
                IOUtil.close( out );
            }

            inputFile.delete();
        }
        else
        {
            if ( pom.getParent() != null )
            {
                pom.getParent().setGroupId( StringUtils.replace( pom.getParent().getGroupId(),
                                                                 pomReversedProperties.getProperty(
                                                                     Constants.GROUP_ID ),
                                                                 "${" + Constants.GROUP_ID + "}" ) );
                if ( pom.getParent().getArtifactId() != null
                    && pom.getParent().getArtifactId().indexOf( rootArtifactId ) >= 0 )
                {
                    pom.getParent().setArtifactId(
                        StringUtils.replace( pom.getParent().getArtifactId(), rootArtifactId, "${rootArtifactId}" ) );
                }
                if ( pom.getParent().getVersion() != null )
                {
                    pom.getParent().setVersion( "${" + Constants.VERSION + "}" );
                }
            }
            pom.setModules( null );

            if ( pom.getGroupId() != null )
            {
                pom.setGroupId(
                    StringUtils.replace( pom.getGroupId(), pomReversedProperties.getProperty( Constants.GROUP_ID ),
                                         "${" + Constants.GROUP_ID + "}" ) );
            }

            pom.setArtifactId( "${" + Constants.ARTIFACT_ID + "}" );

            if ( pom.getVersion() != null )
            {
                pom.setVersion( "${" + Constants.VERSION + "}" );
            }

            pom.setName( getReversedPlainContent( pom.getName(), pomReversedProperties ) );
            pom.setDescription( getReversedPlainContent( pom.getDescription(), pomReversedProperties ) );
            pom.setUrl( getReversedPlainContent( pom.getUrl(), pomReversedProperties ) );

            rewriteReferences( pom, rootArtifactId, pomReversedProperties.getProperty( Constants.GROUP_ID ) );

            pomManager.writePom( pom, outputFile, initialPomFile );
        }

        Reader in = null;
        try
        {
            in = ReaderFactory.newXmlReader( initialPomFile );
            String initialcontent = IOUtil.toString( in );

            for ( Iterator<?> properties = pomReversedProperties.keySet().iterator(); properties.hasNext(); )
            {
                String property = (String) properties.next();

                if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
                {
                    getLogger().warn(
                        "OldArchetype uses ${" + property + "} for internal processing, but file " + initialPomFile
                            + " contains this property already" );
                }
            }
        }
        finally
        {
            IOUtil.close( in );
        }
    }

    private Set<String> getExtensions( List<String> files )
    {
        Set<String> extensions = new HashSet<String>();

        for ( String file : files )
        {
            extensions.add( FileUtils.extension( file ) );
        }

        return extensions;
    }

    private Map<String, List<String>> getGroupsMap( final List<String> files, final int level )
    {
        Map<String, List<String>> groups = new HashMap<String, List<String>>();

        for ( String file : files )
        {
            String directory = PathUtils.getDirectory( file, level );
            // make all groups have unix style
            directory = StringUtils.replace( directory, File.separator, "/" );

            if ( !groups.containsKey( directory ) )
            {
                groups.put( directory, new ArrayList<String>() );
            }

            List<String> group = groups.get( directory );

            String innerPath = file.substring( directory.length() + 1 );
            // make all groups have unix style
            innerPath = StringUtils.replace( innerPath, File.separator, "/" );

            group.add( innerPath );
        }

        getLogger().debug( "Sorted " + groups.size() + " groups in " + files.size() + " files" );
        getLogger().debug( "Sorted Files: " + files );

        return groups;
    }

    private FileSet getPackagedFileSet( final boolean filtered, final Set<String> packagedExtensions,
                                        final String group, final Set<String> unpackagedExtensions,
                                        final List<String> unpackagedFiles, String defaultEncoding )
    {
        List<String> includes = new ArrayList<String>();
        List<String> excludes = new ArrayList<String>();

        for ( String extension : packagedExtensions )
        {
            includes.add( "**/*." + extension );

            if ( unpackagedExtensions.contains( extension ) )
            {
                excludes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
            }
        }

        return createFileSet( excludes, true, filtered, group, includes, defaultEncoding );
    }

    private List<FileSet> getPackagedFileSets( final boolean filtered, final String group,
                                               final List<String> groupFiles, final String packageName,
                                               String defaultEncoding )
    {
        String packageAsDir = StringUtils.replace( packageName, ".", "/" );

        List<FileSet> packagedFileSets = new ArrayList<FileSet>();
        List<String> packagedFiles = archetypeFilesResolver.getPackagedFiles( groupFiles, packageAsDir );
        getLogger().debug( "Found packaged Files:" + packagedFiles );

        List<String> unpackagedFiles = archetypeFilesResolver.getUnpackagedFiles( groupFiles, packageAsDir );
        getLogger().debug( "Found unpackaged Files:" + unpackagedFiles );

        Set<String> packagedExtensions = getExtensions( packagedFiles );
        getLogger().debug( "Found packaged extensions " + packagedExtensions );

        Set<String> unpackagedExtensions = getExtensions( unpackagedFiles );

        if ( !packagedExtensions.isEmpty() )
        {
            packagedFileSets.add(
                getPackagedFileSet( filtered, packagedExtensions, group, unpackagedExtensions, unpackagedFiles,
                                    defaultEncoding ) );
        }

        if ( !unpackagedExtensions.isEmpty() )
        {
            getLogger().debug( "Found unpackaged extensions " + unpackagedExtensions );

            packagedFileSets.add(
                getUnpackagedFileSet( filtered, unpackagedExtensions, unpackagedFiles, group, packagedExtensions,
                                      defaultEncoding ) );
        }

        return packagedFileSets;
    }

    private void setParentArtifactId( Properties properties, String parentArtifactId )
    {
        properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
    }

    private void processFileSet( File basedir, File archetypeFilesDirectory, String directory,
                                 List<String> fileSetResources, boolean packaged, String packageName,
                                 Properties reverseProperties, String defaultEncoding )
        throws IOException
    {
        String packageAsDirectory = StringUtils.replace( packageName, ".", File.separator );

        getLogger().debug( "Package as Directory: Package:" + packageName + "->" + packageAsDirectory );

        for ( String inputFileName : fileSetResources )
        {
            String initialFilename = packaged
                ? StringUtils.replace( inputFileName, packageAsDirectory + File.separator, "" )
                : inputFileName;

            getLogger().debug( "InputFileName:" + inputFileName );

            File inputFile = new File( basedir, inputFileName );

            FileCharsetDetector detector = new FileCharsetDetector( inputFile );

            String fileEncoding = detector.isFound() ? detector.getCharset() : defaultEncoding;

            String initialcontent = IOUtil.toString( new FileInputStream( inputFile ), fileEncoding );

            for ( Iterator<?> properties = reverseProperties.keySet().iterator(); properties.hasNext(); )
            {
                String property = (String) properties.next();

                if ( initialcontent.indexOf( "${" + property + "}" ) > 0 )
                {
                    getLogger().warn(
                        "Archetype uses ${" + property + "} for internal processing, but file " + inputFile
                            + " contains this property already" );
                }
            }

            String content = getReversedContent( initialcontent, reverseProperties );
            String outputFilename = getReversedFilename( initialFilename, reverseProperties );

            getLogger().debug( "OutputFileName:" + outputFilename );

            File outputFile = new File( archetypeFilesDirectory, outputFilename );
            outputFile.getParentFile().mkdirs();

            org.apache.commons.io.IOUtils.write( content, new FileOutputStream( outputFile ), fileEncoding );
        }
    }

    private List<String> removePackage( List<String> sources, String packageAsDirectory )
    {
        if ( sources == null )
        {
            return null;
        }

        List<String> unpackagedSources = new ArrayList<String>( sources.size() );

        for ( String source : sources )
        {
            String unpackagedSource = StringUtils.replace( source, packageAsDirectory, "" );

            unpackagedSources.add( unpackagedSource );
        }

        return unpackagedSources;
    }

    private Properties getReversedProperties( ArchetypeDescriptor archetypeDescriptor, Properties properties )
    {
        Properties reversedProperties = new Properties();

        reversedProperties.putAll( properties );
        reversedProperties.remove( Constants.ARCHETYPE_GROUP_ID );
        reversedProperties.remove( Constants.ARCHETYPE_ARTIFACT_ID );
        reversedProperties.remove( Constants.ARCHETYPE_VERSION );

        String packageName = properties.getProperty( Constants.PACKAGE );
        String packageInPathFormat = getPackageInPathFormat( packageName );
        if ( !packageInPathFormat.equals( packageName ) )
        {
            reversedProperties.setProperty( Constants.PACKAGE_IN_PATH_FORMAT, packageInPathFormat );
        }

        // TODO check that reversed properties are all different and no one is a substring of another?
        // to avoid wrong variable replacements

        return reversedProperties;
    }

    private List<String> resolveFileNames( final Model pom, final File basedir, List<String> excludePatterns )
        throws IOException
    {
        getLogger().debug( "Resolving files for " + pom.getId() + " in " + basedir );

        StringBuffer buff = new StringBuffer( "pom.xml*,archetype.properties*,target/**," );
        for ( Iterator<String> modules = pom.getModules().iterator(); modules.hasNext(); )
        {
            buff.append( ',' ).append( modules.next() ).append( "/**" );
        }

        for ( String defaultExclude : ListScanner.DEFAULTEXCLUDES )
        {
            buff.append( ',' ).append( defaultExclude ).append( "/**" );
        }

        for ( String excludePattern : excludePatterns )
        {
            buff.append( ',' ).append( excludePattern );
        }

        String excludes = PathUtils.convertPathForOS( buff.toString() );

        List<String> fileNames = FileUtils.getFileNames( basedir, "**,.*,**/.*", excludes, false );

        getLogger().debug( "Resolved " + fileNames.size() + " files" );
        getLogger().debug( "Resolved Files:" + fileNames );

        return fileNames;
    }

    private List<FileSet> resolveFileSets( String packageName, List<String> fileNames, List<String> languages,
                                           List<String> filtereds, String defaultEncoding )
    {
        List<FileSet> resolvedFileSets = new ArrayList<FileSet>();
        getLogger().debug(
            "Resolving filesets with package=" + packageName + ", languages=" + languages + " and extentions="
                + filtereds );

        List<String> files = new ArrayList<String>( fileNames );

        StringBuilder languageIncludes = new StringBuilder();

        for ( String language : languages )
        {
            languageIncludes.append( ( ( languageIncludes.length() == 0 ) ? "" : "," ) + language + "/**" );
        }

        getLogger().debug( "Using languages includes " + languageIncludes );

        StringBuilder filteredIncludes = new StringBuilder();
        for ( String filtered : filtereds )
        {
            filteredIncludes.append(
                ( ( filteredIncludes.length() == 0 ) ? "" : "," ) + "**/" + ( filtered.startsWith( "." ) ? "" : "*." )
                    + filtered );
        }

        getLogger().debug( "Using filtered includes " + filteredIncludes );

        /* sourcesMainFiles */
        List<String> sourcesMainFiles =
            archetypeFilesResolver.findSourcesMainFiles( files, languageIncludes.toString() );
        if ( !sourcesMainFiles.isEmpty() )
        {
            files.removeAll( sourcesMainFiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( sourcesMainFiles, filteredIncludes.toString() );
            sourcesMainFiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = sourcesMainFiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
            }

            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
            }
        }

        /* resourcesMainFiles */
        List<String> resourcesMainFiles =
            archetypeFilesResolver.findResourcesMainFiles( files, languageIncludes.toString() );
        if ( !resourcesMainFiles.isEmpty() )
        {
            files.removeAll( resourcesMainFiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( resourcesMainFiles, filteredIncludes.toString() );
            resourcesMainFiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = resourcesMainFiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
            }
        }

        /* sourcesTestFiles */
        List<String> sourcesTestFiles =
            archetypeFilesResolver.findSourcesTestFiles( files, languageIncludes.toString() );
        if ( !sourcesTestFiles.isEmpty() )
        {
            files.removeAll( sourcesTestFiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( sourcesTestFiles, filteredIncludes.toString() );
            sourcesTestFiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = sourcesTestFiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
            }
        }

        /* ressourcesTestFiles */
        List<String> resourcesTestFiles =
            archetypeFilesResolver.findResourcesTestFiles( files, languageIncludes.toString() );
        if ( !resourcesTestFiles.isEmpty() )
        {
            files.removeAll( resourcesTestFiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( resourcesTestFiles, filteredIncludes.toString() );
            resourcesTestFiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = resourcesTestFiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
            }
        }

        /* siteFiles */
        List<String> siteFiles = archetypeFilesResolver.findSiteFiles( files, languageIncludes.toString() );
        if ( !siteFiles.isEmpty() )
        {
            files.removeAll( siteFiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( siteFiles, filteredIncludes.toString() );
            siteFiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = siteFiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
            }
        }

        /* thirdLevelSourcesfiles */
        List<String> thirdLevelSourcesfiles =
            archetypeFilesResolver.findOtherSources( 3, files, languageIncludes.toString() );
        if ( !thirdLevelSourcesfiles.isEmpty() )
        {
            files.removeAll( thirdLevelSourcesfiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( thirdLevelSourcesfiles, filteredIncludes.toString() );
            thirdLevelSourcesfiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = thirdLevelSourcesfiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll( createFileSets( filteredFiles, 3, true, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 3, true, packageName, false, defaultEncoding ) );
            }

            /* thirdLevelResourcesfiles */
            List<String> thirdLevelResourcesfiles =
                archetypeFilesResolver.findOtherResources( 3, files, thirdLevelSourcesfiles,
                                                           languageIncludes.toString() );
            if ( !thirdLevelResourcesfiles.isEmpty() )
            {
                files.removeAll( thirdLevelResourcesfiles );
                filteredFiles =
                    archetypeFilesResolver.getFilteredFiles( thirdLevelResourcesfiles, filteredIncludes.toString() );
                thirdLevelResourcesfiles.removeAll( filteredFiles );
                unfilteredFiles = thirdLevelResourcesfiles;
                if ( !filteredFiles.isEmpty() )
                {
                    resolvedFileSets.addAll(
                        createFileSets( filteredFiles, 3, false, packageName, true, defaultEncoding ) );
                }
                if ( !unfilteredFiles.isEmpty() )
                {
                    resolvedFileSets.addAll(
                        createFileSets( unfilteredFiles, 3, false, packageName, false, defaultEncoding ) );
                }
            }
        } // end if

        /* secondLevelSourcesfiles */
        List<String> secondLevelSourcesfiles =
            archetypeFilesResolver.findOtherSources( 2, files, languageIncludes.toString() );
        if ( !secondLevelSourcesfiles.isEmpty() )
        {
            files.removeAll( secondLevelSourcesfiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( secondLevelSourcesfiles, filteredIncludes.toString() );
            secondLevelSourcesfiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = secondLevelSourcesfiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll( createFileSets( filteredFiles, 2, true, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 2, true, packageName, false, defaultEncoding ) );
            }
        }

        /* secondLevelResourcesfiles */
        List<String> secondLevelResourcesfiles =
            archetypeFilesResolver.findOtherResources( 2, files, languageIncludes.toString() );
        if ( !secondLevelResourcesfiles.isEmpty() )
        {
            files.removeAll( secondLevelResourcesfiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( secondLevelResourcesfiles, filteredIncludes.toString() );
            secondLevelResourcesfiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = secondLevelResourcesfiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( filteredFiles, 2, false, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 2, false, packageName, false, defaultEncoding ) );
            }
        }

        /* rootResourcesfiles */
        List<String> rootResourcesfiles =
            archetypeFilesResolver.findOtherResources( 0, files, languageIncludes.toString() );
        if ( !rootResourcesfiles.isEmpty() )
        {
            files.removeAll( rootResourcesfiles );

            List<String> filteredFiles =
                archetypeFilesResolver.getFilteredFiles( rootResourcesfiles, filteredIncludes.toString() );
            rootResourcesfiles.removeAll( filteredFiles );

            List<String> unfilteredFiles = rootResourcesfiles;
            if ( !filteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( filteredFiles, 0, false, packageName, true, defaultEncoding ) );
            }
            if ( !unfilteredFiles.isEmpty() )
            {
                resolvedFileSets.addAll(
                    createFileSets( unfilteredFiles, 0, false, packageName, false, defaultEncoding ) );
            }
        }

        /**/
        if ( !files.isEmpty() )
        {
            getLogger().info( "Ignored files: " + files );
        }

        return resolvedFileSets;
    }

    private void restoreArtifactId( Properties properties, String artifactId )
    {
        if ( StringUtils.isEmpty( artifactId ) )
        {
            properties.remove( Constants.ARTIFACT_ID );
        }
        else
        {
            properties.setProperty( Constants.ARTIFACT_ID, artifactId );
        }
    }

    private void restoreParentArtifactId( Properties properties, String parentArtifactId )
    {
        if ( StringUtils.isEmpty( parentArtifactId ) )
        {
            properties.remove( Constants.PARENT_ARTIFACT_ID );
        }
        else
        {
            properties.setProperty( Constants.PARENT_ARTIFACT_ID, parentArtifactId );
        }
    }

    private String getReversedContent( String content, Properties properties )
    {
        String result =
            StringUtils.replace( StringUtils.replace( content, "$", "${symbol_dollar}" ), "\\", "${symbol_escape}" );
        result = getReversedPlainContent( result, properties );

        // TODO: Replace velocity to a better engine...
        return "#set( $symbol_pound = '#' )\n" + "#set( $symbol_dollar = '$' )\n" + "#set( $symbol_escape = '\\' )\n"
            + StringUtils.replace( result, "#", "${symbol_pound}" );
    }

    private String getReversedPlainContent( String content, Properties properties )
    {
        String result = content;

        for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
        {
            String propertyKey = (String) propertyIterator.next();

            result = StringUtils.replace( result, properties.getProperty( propertyKey ), "${" + propertyKey + "}" );
        }
        return result;
    }

    private String getReversedFilename( String filename, Properties properties )
    {
        String result = filename;

        for ( Iterator<?> propertyIterator = properties.keySet().iterator(); propertyIterator.hasNext(); )
        {
            String propertyKey = (String) propertyIterator.next();

            result = StringUtils.replace( result, properties.getProperty( propertyKey ), "__" + propertyKey + "__" );
        }

        return result;
    }

    private String getTemplateOutputDirectory()
    {
        return Constants.SRC + File.separator + Constants.MAIN + File.separator + Constants.RESOURCES;
    }

    private FileSet getUnpackagedFileSet( final boolean filtered, final String group, final List<String> groupFiles,
                                          String defaultEncoding )
    {
        Set<String> extensions = getExtensions( groupFiles );

        List<String> includes = new ArrayList<String>();
        List<String> excludes = new ArrayList<String>();

        for ( String extension : extensions )
        {
            includes.add( "**/*." + extension );
        }

        return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
    }

    private FileSet getUnpackagedFileSet( final boolean filtered, final Set<String> unpackagedExtensions,
                                          final List<String> unpackagedFiles, final String group,
                                          final Set<String> packagedExtensions, String defaultEncoding )
    {
        List<String> includes = new ArrayList<String>();
        List<String> excludes = new ArrayList<String>();

        for ( String extension : unpackagedExtensions )
        {
            if ( packagedExtensions.contains( extension ) )
            {
                includes.addAll( archetypeFilesResolver.getFilesWithExtension( unpackagedFiles, extension ) );
            }
            else
            {
                includes.add( "**/*." + extension );
            }
        }

        return createFileSet( excludes, false, filtered, group, includes, defaultEncoding );
    }

    private static final String MAVEN_PROPERTIES =
        "META-INF/maven/org.apache.maven.archetype/archetype-common/pom.properties";

    public String getArchetypeVersion()
    {
        InputStream is = null;

        // This should actually come from the pom.properties at testing but it's not generated and put into the JAR, it
        // happens as part of the JAR plugin which is crap as it makes testing inconsistent.
        String version = "version";

        try
        {
            Properties properties = new Properties();

            is = getClass().getClassLoader().getResourceAsStream( MAVEN_PROPERTIES );

            if ( is != null )
            {
                properties.load( is );

                String property = properties.getProperty( "version" );

                if ( property != null )
                {
                    return property;
                }
            }

            return version;
        }
        catch ( IOException e )
        {
            return version;
        }
        finally
        {
            IOUtil.close( is );
        }
    }
}
