/*-
 * Copyright (c) 2014 Red Hat, Inc.
 *
 * Licensed 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.fedoraproject.xmvn.tools.install.impl;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.fedoraproject.xmvn.artifact.Artifact;
import org.fedoraproject.xmvn.artifact.DefaultArtifact;
import org.fedoraproject.xmvn.config.Configurator;
import org.fedoraproject.xmvn.config.InstallerSettings;
import org.fedoraproject.xmvn.config.PackagingRule;
import org.fedoraproject.xmvn.metadata.ArtifactAlias;
import org.fedoraproject.xmvn.metadata.ArtifactMetadata;
import org.fedoraproject.xmvn.repository.ArtifactContext;
import org.fedoraproject.xmvn.repository.Repository;
import org.fedoraproject.xmvn.repository.RepositoryConfigurator;
import org.fedoraproject.xmvn.repository.RepositoryPath;

@Named
@Singleton
public class DefaultArtifactInstaller
    implements ArtifactInstaller
{
    private final Logger logger = LoggerFactory.getLogger( DefaultArtifactInstaller.class );

    @Inject
    private RepositoryConfigurator repositoryConfigurator;

    @Inject
    private Configurator configurator;

    @Override
    public void install( JavaPackage targetPackage, ArtifactMetadata am, PackagingRule rule )
        throws ArtifactInstallationException
    {
        Artifact artifact =
            new DefaultArtifact( am.getGroupId(), am.getArtifactId(), am.getExtension(), am.getClassifier(),
                                 am.getVersion() );

        Map<String, String> properties = new LinkedHashMap<>();
        for ( String name : am.getProperties().stringPropertyNames() )
            properties.put( name, am.getProperties().getProperty( name ) );

        logger.info( "Installing artifact {}", artifact );

        InstallerSettings settings = configurator.getConfiguration().getInstallerSettings();

        Repository repo = repositoryConfigurator.configureRepository( "install" );
        if ( repo == null )
            throw new ArtifactInstallationException( "Unable to configure installation repository" );

        Set<Path> basePaths = new LinkedHashSet<>();
        for ( String fileName : rule.getFiles() )
            basePaths.add( Paths.get( fileName ) );
        if ( basePaths.isEmpty() )
            basePaths.add( Paths.get( settings.getPackageName() + "/" + artifact.getArtifactId() ) );

        Set<Path> relativePaths = new LinkedHashSet<>();
        Set<Path> absolutePaths = new LinkedHashSet<>();

        for ( Path path : basePaths )
        {
            if ( path.isAbsolute() )
                absolutePaths.add( path );
            else
                relativePaths.add( path );
        }
        if ( relativePaths.isEmpty() )
            throw new RuntimeException( "At least one non-absolute file must be specified for artifact " + artifact );

        String installedVersion = rule.getVersions().isEmpty() ? null : rule.getVersions().iterator().next();
        Artifact versionedArtifact = artifact.setVersion( installedVersion );
        ArtifactContext context = new ArtifactContext( versionedArtifact, properties );
        List<RepositoryPath> repoPaths = new ArrayList<>();
        for ( Path path : relativePaths )
        {
            RepositoryPath repoPath = repo.getPrimaryArtifactPath( versionedArtifact, context, path.toString() );
            if ( repoPath == null )
                throw new ArtifactInstallationException( "Installation repository is incapable of holding artifact "
                    + versionedArtifact );
            repoPaths.add( repoPath );
        }
        Iterator<RepositoryPath> repoPathIterator = repoPaths.iterator();

        // Artifact path
        File artifactFile = new RegularFile( repoPathIterator.next().getPath(), Paths.get( am.getPath() ) );
        targetPackage.addFile( artifactFile );
        Path primaryPath = Paths.get( "/" ).resolve( artifactFile.getTargetPath() );
        am.setPath( primaryPath.toString() );

        // Relative symlinks
        while ( repoPathIterator.hasNext() )
        {
            File symlink = new SymbolicLink( repoPathIterator.next().getPath(), primaryPath );
            targetPackage.addFile( symlink );
        }

        // Absolute symlinks
        for ( Path path : absolutePaths )
        {
            File symlink = new SymbolicLink( Paths.get( "/" ).relativize( path ), primaryPath );
            targetPackage.addFile( symlink );
        }

        // Namespace
        am.setNamespace( repoPaths.iterator().next().getRepository().getNamespace() );

        // UUID
        am.setUuid( UUID.randomUUID().toString() );

        // Compat version
        for ( String version : rule.getVersions() )
            am.addCompatVersion( version );

        // Aliases
        for ( org.fedoraproject.xmvn.config.Artifact aliasArtifact : rule.getAliases() )
        {
            ArtifactAlias alias = new ArtifactAlias();
            alias.setGroupId( aliasArtifact.getGroupId() );
            alias.setArtifactId( aliasArtifact.getArtifactId() );
            alias.setExtension( aliasArtifact.getExtension() );
            alias.setClassifier( aliasArtifact.getClassifier() );
            am.addAlias( alias );
        }

        targetPackage.getMetadata().addArtifact( am );
    }
}

@@ -999,16 +999,61 @@
 leton;%0A%0A
+import org.codehaus.plexus.util.StringUtils;%0A
 import o
@@ -5182,74 +5182,648 @@
     
-File symlink = new SymbolicLink( Paths.get( %22/%22 ).relativize( path
+StringBuilder sb = new StringBuilder( Paths.get( %22/%22 ).relativize( path ).toString() );%0A            if ( !versionedArtifact.getVersion().equals( Artifact.DEFAULT_VERSION ) )%0A                sb.append( '-' ).append( versionedArtifact.getVersion() );%0A            if ( StringUtils.isNotEmpty( versionedArtifact.getClassifier() ) )%0A                sb.append( '-' ).append( versionedArtifact.getClassifier() );%0A            if ( !versionedArtifact.getExtension().equals( Artifact.DEFAULT_VERSION ) )%0A                sb.append( '.' ).append( versionedArtifact.getExtension() );%0A            File symlink = new SymbolicLink( Paths.get( sb.toString()
  ), 

Fix absolute symlinks