Coverage Report - org.apache.maven.project.ProjectSorter
 
Classes in this File Line Coverage Branch Coverage Complexity
ProjectSorter
0%
0/78
0%
0/56
5.167
 
 1  
 package org.apache.maven.project;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *  http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.artifact.ArtifactUtils;
 23  
 import org.apache.maven.model.Dependency;
 24  
 import org.apache.maven.model.Extension;
 25  
 import org.apache.maven.model.Plugin;
 26  
 import org.apache.maven.model.ReportPlugin;
 27  
 import org.codehaus.plexus.util.dag.CycleDetectedException;
 28  
 import org.codehaus.plexus.util.dag.DAG;
 29  
 import org.codehaus.plexus.util.dag.TopologicalSorter;
 30  
 
 31  
 import java.util.ArrayList;
 32  
 import java.util.Collections;
 33  
 import java.util.HashMap;
 34  
 import java.util.Iterator;
 35  
 import java.util.List;
 36  
 import java.util.Map;
 37  
 
 38  
 /**
 39  
  * Sort projects by dependencies.
 40  
  *
 41  
  * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 42  
  * @version $Id: ProjectSorter.java 495147 2007-01-11 07:47:53Z jvanzyl $
 43  
  */
 44  
 public class ProjectSorter
 45  
 {
 46  
     private final DAG dag;
 47  
 
 48  
     private final List sortedProjects;
 49  
 
 50  
     private MavenProject topLevelProject;
 51  
 
 52  
     /**
 53  
      * Sort a list of projects.
 54  
      * <ul>
 55  
      * <li>collect all the vertices for the projects that we want to build.</li>
 56  
      * <li>iterate through the deps of each project and if that dep is within
 57  
      * the set of projects we want to build then add an edge, otherwise throw
 58  
      * the edge away because that dependency is not within the set of projects
 59  
      * we are trying to build. we assume a closed set.</li>
 60  
      * <li>do a topo sort on the graph that remains.</li>
 61  
      * </ul>
 62  
      * @throws DuplicateProjectException if any projects are duplicated by id
 63  
      */
 64  
     public ProjectSorter( List projects )
 65  
         throws CycleDetectedException, DuplicateProjectException
 66  0
     {
 67  0
         dag = new DAG();
 68  
 
 69  0
         Map projectMap = new HashMap();
 70  
 
 71  0
         for ( Iterator i = projects.iterator(); i.hasNext(); )
 72  
         {
 73  0
             MavenProject project = (MavenProject) i.next();
 74  
 
 75  0
             String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
 76  
 
 77  0
             if ( dag.getVertex( id ) != null )
 78  
             {
 79  0
                 throw new DuplicateProjectException( "Project '" + id + "' is duplicated in the reactor" );
 80  
             }
 81  
 
 82  0
             dag.addVertex( id );
 83  
 
 84  0
             projectMap.put( id, project );
 85  0
         }
 86  
 
 87  0
         for ( Iterator i = projects.iterator(); i.hasNext(); )
 88  
         {
 89  0
             MavenProject project = (MavenProject) i.next();
 90  
 
 91  0
             String id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
 92  
 
 93  0
             for ( Iterator j = project.getDependencies().iterator(); j.hasNext(); )
 94  
             {
 95  0
                 Dependency dependency = (Dependency) j.next();
 96  
 
 97  0
                 String dependencyId = ArtifactUtils
 98  
                     .versionlessKey( dependency.getGroupId(), dependency.getArtifactId() );
 99  
 
 100  0
                 if ( dag.getVertex( dependencyId ) != null )
 101  
                 {
 102  0
                     project.addProjectReference( (MavenProject) projectMap.get( dependencyId ) );
 103  
 
 104  0
                     dag.addEdge( id, dependencyId );
 105  
                 }
 106  0
             }
 107  
 
 108  0
             MavenProject parent = project.getParent();
 109  0
             if ( parent != null )
 110  
             {
 111  0
                 String parentId = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
 112  0
                 if ( dag.getVertex( parentId ) != null )
 113  
                 {
 114  
                     // Parent is added as an edge, but must not cause a cycle - so we remove any other edges it has in conflict
 115  0
                     if ( dag.hasEdge( parentId, id ) )
 116  
                     {
 117  0
                         dag.removeEdge( parentId, id );
 118  
                     }
 119  0
                     dag.addEdge( id, parentId );
 120  
                 }
 121  
             }
 122  
 
 123  0
             List buildPlugins = project.getBuildPlugins();
 124  0
             if ( buildPlugins != null )
 125  
             {
 126  0
                 for ( Iterator j = buildPlugins.iterator(); j.hasNext(); )
 127  
                 {
 128  0
                     Plugin plugin = (Plugin) j.next();
 129  0
                     String pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
 130  0
                     if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
 131  
                     {
 132  0
                         addEdgeWithParentCheck( projectMap, pluginId, project, id );
 133  
                     }
 134  0
                 }
 135  
             }
 136  
 
 137  0
             List reportPlugins = project.getReportPlugins();
 138  0
             if ( reportPlugins != null )
 139  
             {
 140  0
                 for ( Iterator j = reportPlugins.iterator(); j.hasNext(); )
 141  
                 {
 142  0
                     ReportPlugin plugin = (ReportPlugin) j.next();
 143  0
                     String pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
 144  0
                     if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
 145  
                     {
 146  0
                         addEdgeWithParentCheck( projectMap, pluginId, project, id );
 147  
                     }
 148  0
                 }
 149  
             }
 150  
 
 151  0
             for ( Iterator j = project.getBuildExtensions().iterator(); j.hasNext(); )
 152  
             {
 153  0
                 Extension extension = (Extension) j.next();
 154  0
                 String extensionId = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
 155  0
                 if ( dag.getVertex( extensionId ) != null )
 156  
                 {
 157  0
                     addEdgeWithParentCheck( projectMap, extensionId, project, id );
 158  
                 }
 159  0
             }
 160  0
         }
 161  
 
 162  0
         List sortedProjects = new ArrayList();
 163  
 
 164  0
         for ( Iterator i = TopologicalSorter.sort( dag ).iterator(); i.hasNext(); )
 165  
         {
 166  0
             String id = (String) i.next();
 167  
 
 168  0
             sortedProjects.add( projectMap.get( id ) );
 169  0
         }
 170  
 
 171  0
         this.sortedProjects = Collections.unmodifiableList( sortedProjects );
 172  0
     }
 173  
 
 174  
     private void addEdgeWithParentCheck( Map projectMap, String projectRefId, MavenProject project, String id )
 175  
         throws CycleDetectedException
 176  
     {
 177  0
         MavenProject extProject = (MavenProject) projectMap.get( projectRefId );
 178  
         
 179  0
         if ( extProject == null )
 180  
         {
 181  0
             return;
 182  
         }
 183  
 
 184  0
         project.addProjectReference( extProject );
 185  
 
 186  0
         MavenProject extParent = extProject.getParent();
 187  0
         if ( extParent != null )
 188  
         {
 189  0
             String parentId = ArtifactUtils.versionlessKey( extParent.getGroupId(), extParent.getArtifactId() );
 190  
             // Don't add edge from parent to extension if a reverse edge already exists
 191  0
             if ( !dag.hasEdge( projectRefId, id ) || !parentId.equals( id ) )
 192  
             {
 193  0
                 dag.addEdge( id, projectRefId );
 194  
             }
 195  
         }
 196  0
     }
 197  
 
 198  
     // TODO: !![jc; 28-jul-2005] check this; if we're using '-r' and there are aggregator tasks, this will result in weirdness.
 199  
     public MavenProject getTopLevelProject()
 200  
     {
 201  0
         if ( topLevelProject == null )
 202  
         {
 203  0
             for ( Iterator i = sortedProjects.iterator(); i.hasNext() && topLevelProject == null; )
 204  
             {
 205  0
                 MavenProject project = (MavenProject) i.next();
 206  0
                 if ( project.isExecutionRoot() )
 207  
                 {
 208  0
                     topLevelProject = project;
 209  
                 }
 210  0
             }
 211  
         }
 212  
 
 213  0
         return topLevelProject;
 214  
     }
 215  
 
 216  
     public List getSortedProjects()
 217  
     {
 218  0
         return sortedProjects;
 219  
     }
 220  
 
 221  
     public boolean hasMultipleProjects()
 222  
     {
 223  0
         return sortedProjects.size() > 1;
 224  
     }
 225  
 
 226  
     public List getDependents( String id )
 227  
     {
 228  0
         return dag.getParentLabels( id );
 229  
     }
 230  
 }