001package org.apache.maven.repository.metadata;
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.ArrayList;
023import java.util.Arrays;
024import java.util.Comparator;
025import java.util.List;
026
027import org.apache.maven.artifact.ArtifactScopeEnum;
028import org.codehaus.plexus.component.annotations.Component;
029import org.codehaus.plexus.component.annotations.Requirement;
030
031/**
032 * default implementation of the metadata classpath transformer
033 *
034 * @author <a href="oleg@codehaus.org">Oleg Gusakov</a>
035 *
036 */
037@Component( role = ClasspathTransformation.class )
038public class DefaultClasspathTransformation
039    implements ClasspathTransformation
040{
041    @Requirement
042    GraphConflictResolver conflictResolver;
043
044    //----------------------------------------------------------------------------------------------------
045    public ClasspathContainer transform( MetadataGraph dirtyGraph, ArtifactScopeEnum scope, boolean resolve )
046        throws MetadataGraphTransformationException
047    {
048        try
049        {
050            if ( dirtyGraph == null || dirtyGraph.isEmpty() )
051            {
052                return null;
053            }
054
055            MetadataGraph cleanGraph = conflictResolver.resolveConflicts( dirtyGraph, scope );
056
057            if ( cleanGraph == null || cleanGraph.isEmpty() )
058            {
059                return null;
060            }
061
062            ClasspathContainer cpc = new ClasspathContainer( scope );
063            if ( cleanGraph.isEmptyEdges() )
064            {
065                // single entry in the classpath, populated from itself
066                ArtifactMetadata amd = cleanGraph.getEntry().getMd();
067                cpc.add( amd );
068            }
069            else
070            {
071                ClasspathGraphVisitor v = new ClasspathGraphVisitor( cleanGraph, cpc );
072                MetadataGraphVertex entry = cleanGraph.getEntry();
073                // entry point
074                v.visit( entry );
075            }
076
077            return cpc;
078        }
079        catch ( GraphConflictResolutionException e )
080        {
081            throw new MetadataGraphTransformationException( e );
082        }
083    }
084
085    //===================================================================================================
086    /**
087     * Helper class to traverse graph. Required to make the containing method thread-safe
088     * and yet use class level data to lessen stack usage in recursion
089     */
090    private class ClasspathGraphVisitor
091    {
092        MetadataGraph graph;
093
094        ClasspathContainer cpc;
095
096        List<MetadataGraphVertex> visited;
097
098        // -----------------------------------------------------------------------
099        protected ClasspathGraphVisitor( MetadataGraph cleanGraph, ClasspathContainer cpc )
100        {
101            this.cpc = cpc;
102            this.graph = cleanGraph;
103
104            visited = new ArrayList<>( cleanGraph.getVertices().size() );
105        }
106
107        // -----------------------------------------------------------------------
108        protected void visit( MetadataGraphVertex node ) // , String version, String artifactUri )
109        {
110            ArtifactMetadata md = node.getMd();
111            if ( visited.contains( node ) )
112            {
113                return;
114            }
115
116            cpc.add( md );
117//
118//            TreeSet<MetadataGraphEdge> deps = new TreeSet<MetadataGraphEdge>(
119//                        new Comparator<MetadataGraphEdge>()
120//                        {
121//                            public int compare( MetadataGraphEdge e1
122//                                              , MetadataGraphEdge e2
123//                                              )
124//                            {
125//                                if( e1.getDepth() == e2.getDepth() )
126//                                {
127//                                    if( e2.getPomOrder() == e1.getPomOrder() )
128//                                        return e1.getTarget().toString().compareTo(e2.getTarget().toString() );
129//
130//                                    return e2.getPomOrder() - e1.getPomOrder();
131//                                }
132//
133//                                return e2.getDepth() - e1.getDepth();
134//                            }
135//                        }
136//                    );
137
138            List<MetadataGraphEdge> exits = graph.getExcidentEdges( node );
139
140            if ( exits != null && exits.size() > 0 )
141            {
142                MetadataGraphEdge[] sortedExits = exits.toArray( new MetadataGraphEdge[exits.size()] );
143                Arrays.sort( sortedExits
144                        ,
145                        new Comparator<MetadataGraphEdge>()
146                        {
147                            public int compare( MetadataGraphEdge e1
148                                            , MetadataGraphEdge e2
149                                            )
150                            {
151                                if ( e1.getDepth() == e2.getDepth() )
152                                {
153                                    if ( e2.getPomOrder() == e1.getPomOrder() )
154                                    {
155                                        return e1.getTarget().toString().compareTo( e2.getTarget().toString() );
156                                    }
157                                    return e2.getPomOrder() - e1.getPomOrder();
158                                }
159
160                                return e2.getDepth() - e1.getDepth();
161                            }
162                        }
163                );
164
165                for ( MetadataGraphEdge e : sortedExits )
166                {
167                    MetadataGraphVertex targetNode = e.getTarget();
168                    targetNode.getMd().setArtifactScope( e.getScope() );
169                    targetNode.getMd().setWhy( e.getSource().getMd().toString() );
170                    visit( targetNode );
171                }
172            }
173
174        }
175        //-----------------------------------------------------------------------
176        //-----------------------------------------------------------------------
177    }
178    //----------------------------------------------------------------------------------------------------
179    //----------------------------------------------------------------------------------------------------
180}
181
182
183