KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > maven > project > ProjectSorter


1 package org.apache.maven.project;
2
3 /*
4  * Copyright 2001-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import org.apache.maven.artifact.ArtifactUtils;
20 import org.apache.maven.model.Dependency;
21 import org.apache.maven.model.Extension;
22 import org.apache.maven.model.Plugin;
23 import org.apache.maven.model.ReportPlugin;
24 import org.codehaus.plexus.util.dag.CycleDetectedException;
25 import org.codehaus.plexus.util.dag.DAG;
26 import org.codehaus.plexus.util.dag.TopologicalSorter;
27
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collections JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34
35 /**
36  * Sort projects by dependencies.
37  *
38  * @author <a HREF="mailto:brett@apache.org">Brett Porter</a>
39  * @version $Id: ProjectSorter.java 328898 2005-10-27 15:40:47Z jdcasey $
40  */

41 public class ProjectSorter
42 {
43     private final DAG dag;
44
45     private final List JavaDoc sortedProjects;
46
47     private MavenProject topLevelProject;
48
49     /**
50      * Sort a list of projects.
51      * <ul>
52      * <li>collect all the vertices for the projects that we want to build.</li>
53      * <li>iterate through the deps of each project and if that dep is within
54      * the set of projects we want to build then add an edge, otherwise throw
55      * the edge away because that dependency is not within the set of projects
56      * we are trying to build. we assume a closed set.</li>
57      * <li>do a topo sort on the graph that remains.</li>
58      * </ul>
59      * @throws DuplicateProjectException if any projects are duplicated by id
60      */

61     public ProjectSorter( List JavaDoc projects )
62         throws CycleDetectedException, DuplicateProjectException
63     {
64         dag = new DAG();
65
66         Map JavaDoc projectMap = new HashMap JavaDoc();
67
68         for ( Iterator JavaDoc i = projects.iterator(); i.hasNext(); )
69         {
70             MavenProject project = (MavenProject) i.next();
71
72             String JavaDoc id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
73
74             if ( dag.getVertex( id ) != null )
75             {
76                 throw new DuplicateProjectException( "Project '" + id + "' is duplicated in the reactor" );
77             }
78             
79             dag.addVertex( id );
80
81             projectMap.put( id, project );
82         }
83
84         for ( Iterator JavaDoc i = projects.iterator(); i.hasNext(); )
85         {
86             MavenProject project = (MavenProject) i.next();
87
88             String JavaDoc id = ArtifactUtils.versionlessKey( project.getGroupId(), project.getArtifactId() );
89
90             for ( Iterator JavaDoc j = project.getDependencies().iterator(); j.hasNext(); )
91             {
92                 Dependency dependency = (Dependency) j.next();
93
94                 String JavaDoc dependencyId = ArtifactUtils.versionlessKey( dependency.getGroupId(),
95                                                                     dependency.getArtifactId() );
96
97                 if ( dag.getVertex( dependencyId ) != null )
98                 {
99                     project.addProjectReference( (MavenProject) projectMap.get( dependencyId ) );
100
101                     dag.addEdge( id, dependencyId );
102                 }
103             }
104
105             MavenProject parent = project.getParent();
106             if ( parent != null )
107             {
108                 String JavaDoc parentId = ArtifactUtils.versionlessKey( parent.getGroupId(), parent.getArtifactId() );
109                 if ( dag.getVertex( parentId ) != null )
110                 {
111                     // Parent is added as an edge, but must not cause a cycle - so we remove any other edges it has in conflict
112
if ( dag.hasEdge( parentId, id ) )
113                     {
114                         dag.removeEdge( parentId, id );
115                     }
116                     dag.addEdge( id, parentId );
117                 }
118             }
119
120             List JavaDoc buildPlugins = project.getBuildPlugins();
121             if ( buildPlugins != null )
122             {
123                 for ( Iterator JavaDoc j = buildPlugins.iterator(); j.hasNext(); )
124                 {
125                     Plugin plugin = (Plugin) j.next();
126                     String JavaDoc pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
127                     if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
128                     {
129                         addEdgeWithParentCheck( projectMap, pluginId, project, id );
130                     }
131                 }
132             }
133
134             List JavaDoc reportPlugins = project.getReportPlugins();
135             if ( reportPlugins != null )
136             {
137                 for ( Iterator JavaDoc j = reportPlugins.iterator(); j.hasNext(); )
138                 {
139                     ReportPlugin plugin = (ReportPlugin) j.next();
140                     String JavaDoc pluginId = ArtifactUtils.versionlessKey( plugin.getGroupId(), plugin.getArtifactId() );
141                     if ( dag.getVertex( pluginId ) != null && !pluginId.equals( id ) )
142                     {
143                         addEdgeWithParentCheck( projectMap, pluginId, project, id );
144                     }
145                 }
146             }
147
148             for ( Iterator JavaDoc j = project.getBuildExtensions().iterator(); j.hasNext(); )
149             {
150                 Extension extension = (Extension) j.next();
151                 String JavaDoc extensionId = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );
152                 if ( dag.getVertex( extensionId ) != null )
153                 {
154                     addEdgeWithParentCheck( projectMap, extensionId, project, id );
155                 }
156             }
157         }
158
159         List JavaDoc sortedProjects = new ArrayList JavaDoc();
160
161         for ( Iterator JavaDoc i = TopologicalSorter.sort( dag ).iterator(); i.hasNext(); )
162         {
163             String JavaDoc id = (String JavaDoc) i.next();
164
165             sortedProjects.add( projectMap.get( id ) );
166         }
167
168         this.sortedProjects = Collections.unmodifiableList( sortedProjects );
169     }
170
171     private void addEdgeWithParentCheck( Map JavaDoc projectMap, String JavaDoc extensionId, MavenProject project, String JavaDoc id )
172         throws CycleDetectedException
173     {
174         MavenProject extProject = (MavenProject) projectMap.get( extensionId );
175         project.addProjectReference( extProject );
176
177         MavenProject extParent = extProject.getParent();
178         if ( extParent != null )
179         {
180             String JavaDoc parentId = ArtifactUtils.versionlessKey( extParent.getGroupId(), extParent.getArtifactId() );
181             // Don't add edge from parent to extension if a reverse edge already exists
182
if ( !dag.hasEdge( extensionId, id ) || !parentId.equals( id ) )
183             {
184                 dag.addEdge( id, extensionId );
185             }
186         }
187     }
188
189     // TODO: !![jc; 28-jul-2005] check this; if we're using '-r' and there are aggregator tasks, this will result in weirdness.
190
public MavenProject getTopLevelProject()
191     {
192         if ( topLevelProject == null )
193         {
194             for ( Iterator JavaDoc i = sortedProjects.iterator(); i.hasNext() && topLevelProject == null; )
195             {
196                 MavenProject project = (MavenProject) i.next();
197                 if ( project.isExecutionRoot() )
198                 {
199                     topLevelProject = project;
200                 }
201             }
202         }
203
204         return topLevelProject;
205     }
206
207     public List JavaDoc getSortedProjects()
208     {
209         return sortedProjects;
210     }
211
212     public boolean hasMultipleProjects()
213     {
214         return sortedProjects.size() > 1;
215     }
216
217     public List JavaDoc getDependents( String JavaDoc id )
218     {
219         return dag.getParentLabels( id );
220     }
221 }
222
Popular Tags