1   package org.apache.maven.repository.metadata;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.TreeSet;
25  
26  import org.apache.maven.artifact.ArtifactScopeEnum;
27  import org.codehaus.plexus.component.annotations.Component;
28  import org.codehaus.plexus.component.annotations.Requirement;
29  
30  
31  
32  
33  
34  
35  @Component( role = GraphConflictResolver.class )
36  public class DefaultGraphConflictResolver
37      implements GraphConflictResolver
38  {
39      
40  
41  
42      @Requirement( role = GraphConflictResolutionPolicy.class )
43      protected GraphConflictResolutionPolicy policy;
44  
45      
46      
47      public MetadataGraph resolveConflicts( MetadataGraph graph, ArtifactScopeEnum scope )
48          throws GraphConflictResolutionException
49      {
50          if ( policy == null )
51          {
52              throw new GraphConflictResolutionException( "no GraphConflictResolutionPolicy injected" );
53          }
54  
55          if ( graph == null )
56          {
57              return null;
58          }
59  
60          final MetadataGraphVertex entry = graph.getEntry();
61          if ( entry == null )
62          {
63              return null;
64          }
65  
66          if ( graph.isEmpty() )
67          {
68              throw new GraphConflictResolutionException( "graph with an entry, but not vertices do not exist" );
69          }
70  
71          if ( graph.isEmptyEdges() )
72          {
73              return null; 
74          }
75  
76          final TreeSet<MetadataGraphVertex> vertices = graph.getVertices();
77  
78          try
79          {
80              
81              if ( vertices.size() == 1 )
82              {
83                  return new MetadataGraph( entry );
84              }
85  
86              final ArtifactScopeEnum requestedScope = ArtifactScopeEnum.checkScope( scope );
87  
88              MetadataGraph res = new MetadataGraph( vertices.size() );
89              res.setVersionedVertices( false );
90              res.setScopedVertices( false );
91  
92              MetadataGraphVertex resEntry = res.addVertex( entry.getMd() );
93              res.setEntry( resEntry );
94  
95              res.setScope( requestedScope );
96  
97              for ( MetadataGraphVertex v : vertices )
98              {
99                  final List<MetadataGraphEdge> ins = graph.getIncidentEdges( v );
100                 final MetadataGraphEdge edge = cleanEdges( v, ins, requestedScope );
101 
102                 if ( edge == null )
103                 { 
104                     if ( entry.equals( v ) )
105                     { 
106                         
107                         res.getEntry().getMd().setWhy( "This is a graph entry point. No links." );
108                     }
109                     else
110                     {
111                         
112                         
113                         
114                         
115                         
116                     }
117                 }
118                 else
119                 {
120                     
121                     
122                     ArtifactMetadata md = v.getMd();
123                     ArtifactMetadata newMd =
124                         new ArtifactMetadata( md.getGroupId(), md.getArtifactId(), edge.getVersion(), md.getType(),
125                                               md.getScopeAsEnum(), md.getClassifier(), edge.getArtifactUri(),
126                                               edge.getSource() == null ? "" : edge.getSource().getMd().toString(),
127                                               edge.isResolved(), edge.getTarget() == null ? null
128                                                               : edge.getTarget().getMd().getError() );
129                     MetadataGraphVertex newV = res.addVertex( newMd );
130                     MetadataGraphVertex sourceV = res.addVertex( edge.getSource().getMd() );
131 
132                     res.addEdge( sourceV, newV, edge );
133                 }
134             }
135             MetadataGraph linkedRes = findLinkedSubgraph( res );
136             
137             
138             
139             
140             return linkedRes;
141         }
142         catch ( MetadataResolutionException e )
143         {
144             throw new GraphConflictResolutionException( e );
145         }
146     }
147 
148     
149     private MetadataGraph findLinkedSubgraph( MetadataGraph g )
150     {
151         if ( g.getVertices().size() == 1 )
152         {
153             return g;
154         }
155 
156         List<MetadataGraphVertex> visited = new ArrayList<MetadataGraphVertex>( g.getVertices().size() );
157         visit( g.getEntry(), visited, g );
158 
159         List<MetadataGraphVertex> dropList = new ArrayList<MetadataGraphVertex>( g.getVertices().size() );
160 
161         
162         for ( MetadataGraphVertex v : g.getVertices() )
163         {
164             if ( !visited.contains( v ) )
165             {
166                 dropList.add( v );
167             }
168         }
169 
170         if ( dropList.size() < 1 )
171         {
172             return g;
173         }
174 
175         
176         TreeSet<MetadataGraphVertex> vertices = g.getVertices();
177         for ( MetadataGraphVertex v : dropList )
178         {
179             vertices.remove( v );
180         }
181 
182         return g;
183     }
184 
185     
186     private void visit( MetadataGraphVertex from, List<MetadataGraphVertex> visited, MetadataGraph graph )
187     {
188         if ( visited.contains( from ) )
189         {
190             return;
191         }
192 
193         visited.add( from );
194 
195         List<MetadataGraphEdge> exitList = graph.getExcidentEdges( from );
196         
197         if ( exitList != null && exitList.size() > 0 )
198         {
199             for ( MetadataGraphEdge e : graph.getExcidentEdges( from ) )
200             {
201                 visit( e.getTarget(), visited, graph );
202             }
203         }
204     }
205 
206     
207     private MetadataGraphEdge cleanEdges( MetadataGraphVertex v, List<MetadataGraphEdge> edges,
208                                           ArtifactScopeEnum scope )
209     {
210         if ( edges == null || edges.isEmpty() )
211         {
212             return null;
213         }
214 
215         if ( edges.size() == 1 )
216         {
217             MetadataGraphEdge e = edges.get( 0 );
218             if ( scope.encloses( e.getScope() ) )
219             {
220                 return e;
221             }
222 
223             return null;
224         }
225 
226         MetadataGraphEdge res = null;
227 
228         for ( MetadataGraphEdge e : edges )
229         {
230             if ( !scope.encloses( e.getScope() ) )
231             {
232                 continue;
233             }
234 
235             if ( res == null )
236             {
237                 res = e;
238             }
239             else
240             {
241                 res = policy.apply( e, res );
242             }
243         }
244 
245         return res;
246     }
247     
248     
249 }