001package org.eclipse.aether.util.graph.transformer;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.Collection;
023import java.util.HashSet;
024import java.util.Set;
025
026import org.eclipse.aether.RepositoryException;
027import org.eclipse.aether.util.artifact.JavaScopes;
028import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
029import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
030import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeSelector;
031
032/**
033 * A scope selector for use with {@link ConflictResolver} that supports the scopes from {@link JavaScopes}. In general,
034 * this selector picks the widest scope present among conflicting dependencies where e.g. "compile" is wider than
035 * "runtime" which is wider than "test". If however a direct dependency is involved, its scope is selected.
036 */
037public final class JavaScopeSelector
038    extends ScopeSelector
039{
040
041    /**
042     * Creates a new instance of this scope selector.
043     */
044    public JavaScopeSelector()
045    {
046    }
047
048    @Override
049    public void selectScope( ConflictContext context )
050        throws RepositoryException
051    {
052        String scope = context.getWinner().getDependency().getScope();
053        if ( !JavaScopes.SYSTEM.equals( scope ) )
054        {
055            scope = chooseEffectiveScope( context.getItems() );
056        }
057        context.setScope( scope );
058    }
059
060    private String chooseEffectiveScope( Collection<ConflictItem> items )
061    {
062        Set<String> scopes = new HashSet<String>();
063        for ( ConflictItem item : items )
064        {
065            if ( item.getDepth() <= 1 )
066            {
067                return item.getDependency().getScope();
068            }
069            scopes.addAll( item.getScopes() );
070        }
071        return chooseEffectiveScope( scopes );
072    }
073
074    private String chooseEffectiveScope( Set<String> scopes )
075    {
076        if ( scopes.size() > 1 )
077        {
078            scopes.remove( JavaScopes.SYSTEM );
079        }
080
081        String effectiveScope = "";
082
083        if ( scopes.size() == 1 )
084        {
085            effectiveScope = scopes.iterator().next();
086        }
087        else if ( scopes.contains( JavaScopes.COMPILE ) )
088        {
089            effectiveScope = JavaScopes.COMPILE;
090        }
091        else if ( scopes.contains( JavaScopes.RUNTIME ) )
092        {
093            effectiveScope = JavaScopes.RUNTIME;
094        }
095        else if ( scopes.contains( JavaScopes.PROVIDED ) )
096        {
097            effectiveScope = JavaScopes.PROVIDED;
098        }
099        else if ( scopes.contains( JavaScopes.TEST ) )
100        {
101            effectiveScope = JavaScopes.TEST;
102        }
103
104        return effectiveScope;
105    }
106
107}