1 package org.apache.continuum.utils;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.continuum.model.project.Project;
23 import org.apache.maven.continuum.model.project.ProjectDependency;
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 import org.slf4j.Logger;
28
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34
35
36
37
38
39
40
41 public class ProjectSorter
42 {
43 private ProjectSorter()
44 {
45
46 }
47
48
49
50
51
52
53
54
55
56
57
58
59 public static List<Project> getSortedProjects( Collection<Project> projects, Logger logger )
60 {
61 DAG dag = new DAG();
62
63 Map<String, Project> projectMap = new HashMap<String, Project>();
64
65 for ( Project project : projects )
66 {
67 String id = getProjectId( project );
68
69 if ( dag.getVertex( id ) != null )
70 {
71 logger.warn( "Project '" + id + "' is duplicated in the reactor." );
72 }
73
74 dag.addVertex( id );
75
76 projectMap.put( id, project );
77 }
78
79 for ( Project project : projects )
80 {
81 String id = getProjectId( project );
82
83 String projectGroupId = "[" + project.getProjectGroup().getId() + "]";
84
85
86 for ( Object o : project.getDependencies() )
87 {
88 ProjectDependency dependency = (ProjectDependency) o;
89
90 String dependencyId = projectGroupId + ":" + getDependencyId( dependency );
91
92 if ( dag.getVertex( dependencyId ) != null )
93 {
94 try
95 {
96 dag.addEdge( id, dependencyId );
97 }
98 catch ( CycleDetectedException e )
99 {
100 logger.warn( "Ignore cycle detected in project dependencies: " + e.getMessage() );
101 }
102 }
103 }
104
105
106 ProjectDependency parent = project.getParent();
107
108 if ( parent != null )
109 {
110 String parentId = projectGroupId + ":" + getDependencyId( parent );
111
112 if ( dag.getVertex( parentId ) != null )
113 {
114
115 if ( dag.hasEdge( parentId, id ) )
116 {
117 dag.removeEdge( parentId, id );
118 }
119 try
120 {
121 dag.addEdge( id, parentId );
122 }
123 catch ( CycleDetectedException e )
124 {
125 logger.warn( "Ignore cycle detected in project parent: " + e.getMessage() );
126 }
127 }
128 }
129 }
130
131 List<Project> sortedProjects = new ArrayList<Project>();
132
133 for ( Object o : TopologicalSorter.sort( dag ) )
134 {
135 String id = (String) o;
136
137 sortedProjects.add( projectMap.get( id ) );
138 }
139
140 return sortedProjects;
141 }
142
143 private static String getProjectId( Project project )
144 {
145 String groupId;
146
147 String artifactId;
148
149 if ( project.getGroupId() == null )
150 {
151 groupId = project.getName();
152 }
153 else
154 {
155 groupId = project.getGroupId();
156 }
157
158 if ( project.getArtifactId() == null )
159 {
160 artifactId = project.getName();
161 }
162 else
163 {
164 artifactId = project.getArtifactId();
165 }
166
167 String projectGroupId = "[" + project.getProjectGroup().getId() + "]";
168
169 return projectGroupId + ":" + groupId + ":" + artifactId + ":" + project.getVersion();
170 }
171
172 private static String getDependencyId( ProjectDependency project )
173 {
174 return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion();
175 }
176 }