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                ArtifactMetadata md = entry.getMd();
074                // entry point
075                v.visit( entry ); // , md.getVersion(), md.getArtifactUri() );
076            }
077
078            return cpc;
079        }
080        catch ( GraphConflictResolutionException e )
081        {
082            throw new MetadataGraphTransformationException( e );
083        }
084    }
085
086    //===================================================================================================
087    /**
088     * Helper class to traverse graph. Required to make the containing method thread-safe
089     * and yet use class level data to lessen stack usage in recursion
090     */
091    private class ClasspathGraphVisitor
092    {
093        MetadataGraph graph;
094
095        ClasspathContainer cpc;
096
097        List<MetadataGraphVertex> visited;
098
099        // -----------------------------------------------------------------------
100        protected ClasspathGraphVisitor( MetadataGraph cleanGraph, ClasspathContainer cpc )
101        {
102            this.cpc = cpc;
103            this.graph = cleanGraph;
104
105            visited = new ArrayList<MetadataGraphVertex>( cleanGraph.getVertices().size() );
106        }
107
108        // -----------------------------------------------------------------------
109        protected void visit( MetadataGraphVertex node ) // , String version, String artifactUri )
110        {
111            ArtifactMetadata md = node.getMd();
112            if ( visited.contains( node ) )
113            {
114                return;
115            }
116
117            cpc.add( md );
118//
119//            TreeSet<MetadataGraphEdge> deps = new TreeSet<MetadataGraphEdge>(
120//                        new Comparator<MetadataGraphEdge>()
121//                        {
122//                            public int compare( MetadataGraphEdge e1
123//                                              , MetadataGraphEdge e2
124//                                              )
125//                            {
126//                                if( e1.getDepth() == e2.getDepth() )
127//                                {
128//                                    if( e2.getPomOrder() == e1.getPomOrder() )
129//                                        return e1.getTarget().toString().compareTo(e2.getTarget().toString() );
130//
131//                                    return e2.getPomOrder() - e1.getPomOrder();
132//                                }
133//
134//                                return e2.getDepth() - e1.getDepth();
135//                            }
136//                        }
137//                    );
138
139            List<MetadataGraphEdge> exits = graph.getExcidentEdges( node );
140
141            if ( exits != null && exits.size() > 0 )
142            {
143                MetadataGraphEdge[] sortedExits = exits.toArray( new MetadataGraphEdge[exits.size()] );
144                Arrays.sort( sortedExits
145                        ,
146                        new Comparator<MetadataGraphEdge>()
147                        {
148                            public int compare( MetadataGraphEdge e1
149                                            , MetadataGraphEdge e2
150                                            )
151                            {
152                                if ( e1.getDepth() == e2.getDepth() )
153                                {
154                                    if ( e2.getPomOrder() == e1.getPomOrder() )
155                                    {
156                                        return e1.getTarget().toString().compareTo( e2.getTarget().toString() );
157                                    }
158                                    return e2.getPomOrder() - e1.getPomOrder();
159                                }
160
161                                return e2.getDepth() - e1.getDepth();
162                            }
163                        }
164                );
165
166                for ( MetadataGraphEdge e : sortedExits )
167                {
168                    MetadataGraphVertex targetNode = e.getTarget();
169                    targetNode.getMd().setArtifactScope( e.getScope() );
170                    targetNode.getMd().setWhy( e.getSource().getMd().toString() );
171                    visit( targetNode );
172                }
173            }
174
175        }
176        //-----------------------------------------------------------------------
177        //-----------------------------------------------------------------------
178    }
179    //----------------------------------------------------------------------------------------------------
180    //----------------------------------------------------------------------------------------------------
181}
182
183
184