001    package 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    
022    import java.util.ArrayList;
023    import java.util.Arrays;
024    import java.util.Comparator;
025    import java.util.List;
026    
027    import org.apache.maven.artifact.ArtifactScopeEnum;
028    import org.codehaus.plexus.component.annotations.Component;
029    import 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 )
038    public 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