/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.sling.maven.slingstart;

import org.apache.commons.io.IOUtils;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
import org.apache.maven.project.MavenProject;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.MergeUtility;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.ModelConstants;
import org.apache.sling.provisioning.model.ModelResolveUtility;
import org.apache.sling.provisioning.model.ModelUtility;
import org.apache.sling.provisioning.model.ModelUtility.ResolverOptions;
import org.apache.sling.provisioning.model.RunMode;
import org.apache.sling.provisioning.model.Traceable;
import org.apache.sling.provisioning.model.io.ModelReader;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.xml.Xpp3Dom;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ModelPreprocessor {

    public static final class ProjectInfo {

        public MavenProject project;
        public Plugin       plugin;
        public Model        localModel;
        public boolean      done = false;
        public Model        model;
        public boolean      extendMavenClassPath = true;
        public final Map<org.apache.sling.provisioning.model.Artifact, Model> includedModels = new HashMap<>();

    }

    public static final class Environment {
        public ArtifactHandlerManager artifactHandlerManager;
        public ArtifactResolver resolver;
        public MavenSession session;
        public Logger logger;
        public final Map<String, ProjectInfo> modelProjects = new HashMap<>();
    }

    /**
     * Add dependencies for all projects.
     * @param env The environment with all maven settings and projects
     * @throws MavenExecutionException If anything goes wrong.
     */
    public void addDependencies(final Environment env) throws MavenExecutionException {
        for(final ProjectInfo info : env.modelProjects.values()) {
            addDependencies(env, info);
        }
    }

    /**
     * Add dependencies for a single project.
     * @param env The environment with all maven settings and projects
     * @param info The project to process.
     * @throws MavenExecutionException If anything goes wrong.
     */
    private Model addDependencies(final Environment env, final ProjectInfo info)
    throws MavenExecutionException {
        if ( info.done == true ) {
            env.logger.debug("Return prepared model for " + info.project);
            return info.model;
        }
        // prevent recursion and multiple processing
        info.done = true;
        env.logger.debug("Processing project " + info.project);

        // read local model
        final String pattern = nodeValue(info.plugin,
                "modelPattern", AbstractSlingStartMojo.DEFAULT_MODEL_PATTERN);

        final String inlinedModel = nodeValue(info.plugin,
                "model", null);

        String scope = Artifact.SCOPE_PROVIDED;
        try {
            if (hasNodeValue(info.plugin, "modelDirectory")) {
                final String directory = nodeValue(info.plugin,
                        "modelDirectory", null);
                info.localModel = readLocalModel(info.project, inlinedModel, new File(directory), pattern, env.logger);
            } else {
                // use multiple fallbacks here only in case the default model directory is not explicitly set
                File defaultModelDirectory = new File(info.project.getBasedir(), "src/main/provisioning");
                File defaultConvertedModelDirectory = new File(info.project.getBuild().getDirectory() + "/" + FeatureModelConverter.BUILD_DIR);

                if (defaultModelDirectory.exists() && defaultConvertedModelDirectory.exists()) {
                    // The model is partially converted, partially explicitly defined. Copy the defined ones in with the converted ones
                    for (File f : defaultModelDirectory.listFiles()) {
                        File targetFile = new File(defaultConvertedModelDirectory, f.getName());
                        if (targetFile.exists()) {
                            env.logger.debug("File already exists. Skipping: " + targetFile);
                        } else {
                            env.logger.debug("Copying " + f + " to " + targetFile);
                            Files.copy(f.toPath(), targetFile.toPath());
                        }
                    }
                } else {
                    env.logger.debug("Try to extract model from default provisioning directory " + defaultModelDirectory.getAbsolutePath());
                    info.localModel = readLocalModel(info.project, inlinedModel, defaultModelDirectory, pattern, env.logger);
                }

                if (defaultConvertedModelDirectory.exists()) {
                    env.logger.debug("Try to extract model from generated provisioning model directory " + defaultConvertedModelDirectory.getAbsolutePath());
                    info.localModel = readLocalModel(info.project, inlinedModel, defaultConvertedModelDirectory, pattern, env.logger);
                }

                if (info.localModel == null) {
                    File defaultModelDirectoryInTest = new File(info.project.getBasedir(), "src/test/provisioning");
                    env.logger.debug("Try to extract model from default test provisioning directory " + defaultModelDirectoryInTest.getAbsolutePath());
                    info.localModel = readLocalModel(info.project, inlinedModel, defaultModelDirectoryInTest, pattern, env.logger);
                    scope = Artifact.SCOPE_TEST;
                }
            }
        } catch ( final IOException ioe) {
            throw new MavenExecutionException(ioe.getMessage(), ioe);
        }

        // process attachments
        processAttachments(env, info);

        // is the maven classpath supposed to be extended?
        info.extendMavenClassPath = !nodeBooleanValue(info.plugin, AbstractSlingStartMojo.CONFIGURATION_NAME_DISABLE_EXTENDING_CLASSPATH, false);

        // check for setting version
        if ( nodeBooleanValue(info.plugin, "setFeatureVersions", false) ) {
            for(final Feature f : info.localModel.getFeatures() ) {
                if ( f.getVersion() == null ) {
                    f.setVersion(cleanupVersion(info.project.getVersion()));
                }
            }
        }

        // prepare resolver options
        ResolverOptions resolverOptions = new ResolverOptions();
        if (nodeBooleanValue(info.plugin, "usePomVariables", false)) {
            resolverOptions.variableResolver(new PomVariableResolver(info.project));
        }
        if (nodeBooleanValue(info.plugin, "usePomDependencies", false)) {
            resolverOptions.artifactVersionResolver(new PomArtifactVersionResolver(info.project,
                    nodeBooleanValue(info.plugin, "allowUnresolvedPomDependencies", false)));
        }

        final Model copyModel = new Model();
        this.mergeModels(copyModel, info.localModel);

        // we have to create an effective model to add the dependencies
        final Model effectiveModel = ModelUtility.getEffectiveModel(copyModel, resolverOptions);

        final List<Model> dependencies = searchSlingstartDependencies(env, info, copyModel, effectiveModel, resolverOptions);
        info.model = new Model();
        for(final Model d : dependencies) {
            this.mergeModels(info.model, d);
        }
        this.mergeModels(info.model, copyModel);
        info.model = ModelUtility.getEffectiveModel(info.model, resolverOptions);

        final Map<Traceable, String> errors = ModelUtility.validate(info.model);
        if ( errors != null ) {
            throw new MavenExecutionException("Unable to create model file for " + info.project + " : " + errors, (File)null);
        }

        if (info.extendMavenClassPath) {
            addDependenciesFromModel(env, info, scope);
            env.logger.info("Extended Maven classpath (scope '" + scope + "') by the dependencies extracted from the Sling model.");
        } else {
            env.logger.debug("Do not enrich Maven classpath with Sling model!");
        }

        try {
           ProjectHelper.storeProjectInfo(info);
        } catch ( final IOException ioe) {
            throw new MavenExecutionException(ioe.getMessage(), ioe);
        }
        return info.model;
    }

    /**
     * Add all dependencies from the model
     * @param env The environment
     * @param info The project info
     * @param scope The scope which the new dependencies should have
     * @throws MavenExecutionException
     */
    private void addDependenciesFromModel(
            final Environment env,
            final ProjectInfo info,
            final String scope)
    throws MavenExecutionException {
        if ( info.project.getPackaging().equals(BuildConstants.PACKAGING_SLINGSTART ) ) {
            // add base artifact if defined in current model
            final org.apache.sling.provisioning.model.Artifact baseArtifact = ModelUtils.findBaseArtifact(info.model);

            final String[] classifiers = new String[] {null, BuildConstants.CLASSIFIER_APP, BuildConstants.CLASSIFIER_WEBAPP};
            for(final String c : classifiers) {
                final Dependency dep = new Dependency();
                dep.setGroupId(baseArtifact.getGroupId());
                dep.setArtifactId(baseArtifact.getArtifactId());
                dep.setVersion(baseArtifact.getVersion());
                dep.setType(baseArtifact.getType());
                dep.setClassifier(c);
                if ( BuildConstants.CLASSIFIER_WEBAPP.equals(c) ) {
                    dep.setType(BuildConstants.TYPE_WAR);
                }
                dep.setScope(scope);

                info.project.getDependencies().add(dep);
                env.logger.debug("- adding base dependency " + ModelUtils.toString(dep));
            }
        }

        for(final Feature feature : info.model.getFeatures()) {
            // skip launchpad feature
            if ( feature.getName().equals(ModelConstants.FEATURE_LAUNCHPAD) ) {
                continue;
            }
            for(final RunMode runMode : feature.getRunModes()) {
                for(final ArtifactGroup group : runMode.getArtifactGroups()) {
                    for(final org.apache.sling.provisioning.model.Artifact a : group) {
                        if ( a.getGroupId().equals(info.project.getGroupId())
                             && a.getArtifactId().equals(info.project.getArtifactId())
                             && a.getVersion().equals(info.project.getVersion()) ) {
                            // skip artifact from the same project
                            env.logger.debug("- skipping dependency " + a.toMvnUrl());
                            continue;
                        }
                        final Dependency dep = new Dependency();
                        dep.setGroupId(a.getGroupId());
                        dep.setArtifactId(a.getArtifactId());
                        dep.setVersion(a.getVersion());
                        dep.setType(a.getType());
                        dep.setClassifier(a.getClassifier());

                        dep.setScope(scope);

                        env.logger.debug("- adding dependency " + ModelUtils.toString(dep));
                        info.project.getDependencies().add(dep);
                    }
                }
            }
        }
    }

    /**
     * Search for dependent slingstart/slingfeature artifacts and remove them from the effective model.
     * @throws MavenExecutionException
     */
    private List<Model> searchSlingstartDependencies(
            final Environment env,
            final ProjectInfo info,
            final Model rawModel,
            final Model effectiveModel,
            final ResolverOptions resolverOptions)
    throws MavenExecutionException {
        // slingstart or slingfeature
        final List<Model> dependencies = new ArrayList<>();

        for(final Feature feature : effectiveModel.getFeatures()) {
            for(final RunMode runMode : feature.getRunModes()) {
                for(final ArtifactGroup group : runMode.getArtifactGroups()) {
                    final List<org.apache.sling.provisioning.model.Artifact> removeList = new ArrayList<>();
                    for(final org.apache.sling.provisioning.model.Artifact a : group) {
                        if ( a.getType().equals(BuildConstants.PACKAGING_SLINGSTART)
                             || a.getType().equals(BuildConstants.PACKAGING_PARTIAL_SYSTEM)) {

                            final Dependency dep = new Dependency();
                            dep.setGroupId(a.getGroupId());
                            dep.setArtifactId(a.getArtifactId());
                            dep.setVersion(a.getVersion());
                            dep.setType(BuildConstants.PACKAGING_PARTIAL_SYSTEM);
                            if ( a.getType().equals(BuildConstants.PACKAGING_SLINGSTART) ) {
                                dep.setClassifier(BuildConstants.PACKAGING_PARTIAL_SYSTEM);
                            } else {
                                dep.setClassifier(a.getClassifier());
                            }
                            dep.setScope(Artifact.SCOPE_PROVIDED);

                            env.logger.debug("- adding dependency " + ModelUtils.toString(dep));
                            info.project.getDependencies().add(dep);

                            // if it's a project from the current reactor build, we can't resolve it right now
                            final String key = a.getGroupId() + ":" + a.getArtifactId();
                            final ProjectInfo depInfo = env.modelProjects.get(key);
                            if ( depInfo != null ) {
                                env.logger.debug("Found reactor " + a.getType() + " dependency : " + a);
                                final Model model = addDependencies(env, depInfo);
                                if ( model == null ) {
                                    throw new MavenExecutionException("Recursive model dependency list including project " + info.project, (File)null);
                                }
                                dependencies.add(model);
                                info.includedModels.put(a, depInfo.localModel);

                            } else {
                                env.logger.debug("Found external " + a.getType() + " dependency: " + a);

                                // "external" dependency, we can already resolve it
                                final File modelFile = resolveSlingstartArtifact(env, info.project, dep);
                                FileReader r = null;
                                try {
                                    r = new FileReader(modelFile);
                                    final Model model = ModelReader.read(r, modelFile.getAbsolutePath());

                                    info.includedModels.put(a, model);

                                    final Map<Traceable, String> errors = ModelUtility.validate(model);
                                    if ( errors != null ) {
                                        throw new MavenExecutionException("Unable to read model file from " + modelFile + " : " + errors, modelFile);
                                    }
                                    final Model fullModel = processSlingstartDependencies(env, info, dep,  model, resolverOptions);

                                    dependencies.add(fullModel);
                                } catch ( final IOException ioe) {
                                    throw new MavenExecutionException("Unable to read model file from " + modelFile, ioe);
                                } finally {
                                    try {
                                        if ( r != null ) {
                                            r.close();
                                        }
                                    } catch ( final IOException io) {
                                        // ignore
                                    }
                                }
                            }

                            removeList.add(a);
                        }
                    }
                    for(final org.apache.sling.provisioning.model.Artifact r : removeList) {
                        group.remove(r);
                        final Feature localModelFeature = rawModel.getFeature(feature.getName());
                        if ( localModelFeature != null ) {
                            final RunMode localRunMode = localModelFeature.getRunMode(runMode.getNames());
                            if ( localRunMode != null ) {
                                final ArtifactGroup localAG = localRunMode.getArtifactGroup(group.getStartLevel());
                                if ( localAG != null ) {
                                    removeArtifact(localModelFeature, localAG, r, resolverOptions);
                                }
                            }
                        }
                    }
                }
            }
        }

        return dependencies;
    }

    private static void removeArtifact(Feature feature, ArtifactGroup group, org.apache.sling.provisioning.model.Artifact toRemove, ResolverOptions resolverOptions) {
        Iterator<org.apache.sling.provisioning.model.Artifact> it = group.iterator();
        while (it.hasNext()) {
            org.apache.sling.provisioning.model.Artifact el = it.next();

            String version = ModelResolveUtility.replace(feature, el.getVersion(), resolverOptions.getVariableResolver());
            org.apache.sling.provisioning.model.Artifact resolved;
            if (el.getVersion().equals(version)) {
                resolved = el;
            } else {
                resolved = new org.apache.sling.provisioning.model.Artifact(el.getGroupId(), el.getArtifactId(), version, el.getClassifier(), el.getType());
            }
            if (resolved.equals(toRemove)) {
                it.remove();
            }
        }
    }

    private Model processSlingstartDependencies(final Environment env, final ProjectInfo info, final Dependency dep, final Model rawModel, ResolverOptions resolverOptions)
    throws MavenExecutionException {
        env.logger.debug("Processing dependency " + dep);

        // we have to create an effective model to add the dependencies
        final Model effectiveModel = ModelUtility.getEffectiveModel(rawModel, new ResolverOptions());

        final List<Model> dependencies = searchSlingstartDependencies(env, info, rawModel, effectiveModel, resolverOptions);
        Model mergingModel = new Model();
        for(final Model d : dependencies) {
            this.mergeModels(mergingModel, d);
        }
        this.mergeModels(mergingModel, rawModel);

        final Map<Traceable, String> errors = ModelUtility.validate(ModelUtility.getEffectiveModel(mergingModel, new ResolverOptions()));
        if ( errors != null ) {
            throw new MavenExecutionException("Unable to create model file for " + dep + " : " + errors, (File)null);
        }

        return mergingModel;
    }

    /**
     * Gets plugins configuration from POM (string parameter).
     * @param plugin Plugin
     * @param name Configuration parameter.
     * @param defaultValue Default value that is returned if parameter is not set
     * @return Parameter value or default value.
     */
    private String nodeValue(final Plugin plugin, final String name, final String defaultValue) {
        final Xpp3Dom config = plugin == null ? null : (Xpp3Dom)plugin.getConfiguration();
        return nodeValue(config, name, defaultValue);
    }

    private String nodeValue(final Xpp3Dom config, final String name, final String defaultValue) {
        final Xpp3Dom node = (config == null ? null : config.getChild(name));
        if (node != null) {
            return node.getValue();
        } else {
            return defaultValue;
        }
    }

    /**
     * Checks if plugin configuration value is set in POM for a specific configuration parameter.
     * @param plugin Plugin
     * @param name Configuration parameter.
     * @return {@code true} in case the configuration has been set in the pom, otherwise {@code false}
     */
    private boolean hasNodeValue(final Plugin plugin, final String name) {
        final Xpp3Dom config = plugin == null ? null : (Xpp3Dom)plugin.getConfiguration();
        final Xpp3Dom node = (config == null ? null : config.getChild(name));
        return (node != null);
    }

    private void processAttachments(final Environment env, final ProjectInfo info)
    throws MavenExecutionException {
        final Xpp3Dom config = info.plugin == null ? null : (Xpp3Dom)info.plugin.getConfiguration();
        final Xpp3Dom[] nodes = (config == null ? null : config.getChildren("attach"));
        if ( nodes != null ) {
            for(final Xpp3Dom node : nodes) {
                final String type = nodeValue(node, "type", null);
                if ( type == null ) {
                    throw new MavenExecutionException("Attachment for provisioning model has no type.", (File)null);
                }
                final String classifier = nodeValue(node, "classifier", null);
                final String featureName = nodeValue(node, "feature", null);
                int startLevel = 0;
                final String level = nodeValue(node, "startLevel", null);
                if ( level != null ) {
                    startLevel = Integer.valueOf(level);
                }

                final Feature f;
                if ( featureName != null ) {
                    f = info.localModel.getFeature(featureName);
                } else if ( info.localModel.getFeatures().isEmpty() ) {
                    f = null;
                } else {
                    f = info.localModel.getFeatures().get(0);
                }
                if ( f == null ) {
                    if ( featureName == null ) {
                        throw new MavenExecutionException("No feature found in provisioning model for attachment.", (File)null);
                    }
                    throw new MavenExecutionException("Feature with name '" + featureName + "' not found in provisioning model for attachment.", (File)null);
                }
                final RunMode runMode = f.getOrCreateRunMode(null);
                final ArtifactGroup group = runMode.getOrCreateArtifactGroup(startLevel);

                final org.apache.sling.provisioning.model.Artifact artifact = new org.apache.sling.provisioning.model.Artifact(
                        info.project.getGroupId(),
                        info.project.getArtifactId(),
                        info.project.getVersion(),
                        classifier,
                        type);

                env.logger.debug("Attaching " + artifact + " to feature " + f.getName());
                group.add(artifact);
            }
        }
    }

    /**
     * Gets plugins configuration from POM (boolean parameter).
     * @param plugin Plugin
     * @param name Configuration parameter.
     * @param defaultValue Default value that is returned if parameter is not set
     * @return Parameter value or default value.
     */
    private boolean nodeBooleanValue(final Plugin plugin, final String name, final boolean defaultValue) {
        String booleanValue = nodeValue(plugin, name, Boolean.toString(defaultValue));
        return "true".equals(booleanValue.toLowerCase());
    }

    private File resolveSlingstartArtifact(final Environment env,
            final MavenProject project,
            final Dependency d)
    throws MavenExecutionException {
        final Artifact prjArtifact = new DefaultArtifact(d.getGroupId(),
                d.getArtifactId(),
                VersionRange.createFromVersion(d.getVersion()),
                Artifact.SCOPE_PROVIDED,
                d.getType(),
                d.getClassifier(),
                env.artifactHandlerManager.getArtifactHandler(d.getType()));
        try {
            env.resolver.resolve(prjArtifact, project.getRemoteArtifactRepositories(), env.session.getLocalRepository());
        } catch (final ArtifactResolutionException e) {
            throw new MavenExecutionException("Unable to get artifact for " + d, e);
        } catch (final ArtifactNotFoundException e) {
            throw new MavenExecutionException("Unable to get artifact for " + d, e);
        }
        return prjArtifact.getFile();
    }

    /**
     * Read all model files from the directory in alphabetical order.
     * Only files ending with .txt or .model are read.
     *
     * @param project The current maven project
     * @param inlinedModel the inlined model to be merged with the models in modelDirectory (may be null)
     * @param modelDirectory The directory to scan for models
     * @param pattern Pattern used to find the textual models within the modelDirectory
     * @param logger The logger
     */
    protected Model readLocalModel(
            final MavenProject project,
            final String inlinedModel,
            final File modelDirectory,
            final String pattern,
            final Logger logger)
    throws MavenExecutionException, IOException {
        final Pattern p = Pattern.compile(pattern);
        final List<String> candidates = new ArrayList<>();
        if ( modelDirectory != null && modelDirectory.exists() ) {
            for(final File f : modelDirectory.listFiles() ) {
                if ( f.isFile() && !f.getName().startsWith(".") ) {
                    if ( p.matcher(f.getName()).matches() ) {
                        candidates.add(f.getName());
                    }
                }
            }
            Collections.sort(candidates);
        }
        if ( candidates.size() == 0 && (inlinedModel == null || inlinedModel.trim().length() == 0) ) {
            throw new MavenExecutionException("No model files found in " + modelDirectory + ", and no model inlined in POM.", (File)null);
        }
        final Model result = new Model();
        if ( inlinedModel != null ) {
            logger.debug("Reading inlined model from project " + project.getId());
            try {
                final Reader reader = new StringReader(inlinedModel);
                try {
                    final Model current = ModelReader.read(reader, "pom");
                    final Map<Traceable, String> errors = ModelUtility.validate(current);
                    if (errors != null ) {
                        throw new MavenExecutionException("Invalid inlined model : " + errors, (File)null);
                    }
                    MergeUtility.merge(result, current, new MergeUtility.MergeOptions().setHandleRemoveRunMode(false));
                } finally {
                    IOUtils.closeQuietly(reader);
                }
            } catch ( final IOException io) {
                throw new MavenExecutionException("Unable to read inlined model", io);
            }
        }
        for(final String name : candidates) {
            logger.debug("Reading model " + name + " in project " + project.getId());
            try {
                final File f = new File(modelDirectory, name);
                final FileReader reader = new FileReader(f);
                try {
                    final Model current = ModelReader.read(reader, f.getAbsolutePath());
                    final Map<Traceable, String> errors = ModelUtility.validate(current);
                    if (errors != null ) {
                        throw new MavenExecutionException("Invalid model at " + name + " : " + errors, (File)null);
                    }
                    MergeUtility.merge(result, current, new MergeUtility.MergeOptions().setHandleRemoveRunMode(false));
                } finally {
                    IOUtils.closeQuietly(reader);
                }
            } catch ( final IOException io) {
                throw new MavenExecutionException("Unable to read model at " + name, io);
            }
        }

        final Map<Traceable, String> errors = ModelUtility.validate(result);
        if (errors != null ) {
            throw new MavenExecutionException("Invalid assembled model : " + errors, (File)null);
        }

        return postProcessReadModel(result);
    }

    /**
     * Hook to post process the local model
     * @param result The read model
     * @return The post processed model
     */
    protected Model postProcessReadModel(final Model result)  throws MavenExecutionException {
        return result;
    }

    /**
     * Hook to change the merge behavior
     * @param base The base model
     * @param additional The additional model
     */
    protected void mergeModels(final Model base, final Model additional) throws MavenExecutionException {
        MergeUtility.merge(base, additional);
    }

    /**
     * Pattern for converting Maven to OSGi version
     * Based on the DefaultMaven2OsgiConverter from the Apache Maven Project.
     */
    private static final Pattern FUZZY_VERSION = Pattern.compile( "(\\d+)(\\.(\\d+)(\\.(\\d+))?)?([^a-zA-Z0-9](.*))?",
        Pattern.DOTALL );


    private String cleanupVersion( final String version ) {
        final StringBuilder result = new StringBuilder();
        final Matcher m = FUZZY_VERSION.matcher( version );
        if ( m.matches() ) {
            final String major = m.group( 1 );
            final String minor = m.group( 3 );
            final String micro = m.group( 5 );
            final String qualifier = m.group( 7 );

            if ( major != null ) {
                result.append( major );
                if ( minor != null ) {
                    result.append( "." );
                    result.append( minor );
                    if ( micro != null ) {
                        result.append( "." );
                        result.append( micro );
                        if ( qualifier != null )
                        {
                            result.append( "." );
                            cleanupModifier( result, qualifier );
                        }
                    } else if ( qualifier != null ) {
                        result.append( ".0." );
                        cleanupModifier( result, qualifier );
                    } else {
                        result.append( ".0" );
                    }
                } else if ( qualifier != null ) {
                    result.append( ".0.0." );
                    cleanupModifier( result, qualifier );
                } else {
                    result.append( ".0.0" );
                }
            }
        } else {
            result.append( "0.0.0." );
            cleanupModifier( result, version );
        }
        return result.toString();
    }

    private static void cleanupModifier( final StringBuilder result, final String modifier )  {
        for ( int i = 0; i < modifier.length(); i++ ) {
            final char c = modifier.charAt( i );
            if ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_'
                || c == '-' ) {
                result.append( c );
            } else {
                result.append( '_' );
            }
        }
    }
}
