1 package org.apache.maven.shared.dependency.graph.internal.maven30;
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.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.IdentityHashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.ListIterator;
32 import java.util.Map;
33
34 import org.sonatype.aether.RepositoryException;
35 import org.sonatype.aether.artifact.Artifact;
36 import org.sonatype.aether.collection.DependencyGraphTransformationContext;
37 import org.sonatype.aether.collection.DependencyGraphTransformer;
38 import org.sonatype.aether.graph.Dependency;
39 import org.sonatype.aether.graph.DependencyNode;
40 import org.sonatype.aether.util.ConfigUtils;
41 import org.sonatype.aether.util.graph.DefaultDependencyNode;
42 import org.sonatype.aether.util.graph.transformer.TransformationContextKeys;
43
44
45
46
47
48
49
50 public final class ConflictResolver
51 implements DependencyGraphTransformer
52 {
53
54
55
56
57
58 public static final String CONFIG_PROP_VERBOSE = "aether.conflictResolver.verbose";
59
60
61
62
63
64 public static final String NODE_DATA_WINNER = "conflict.winner";
65
66
67
68
69
70 public static final String NODE_DATA_ORIGINAL_SCOPE = "conflict.originalScope";
71
72
73
74
75
76 public static final String NODE_DATA_ORIGINAL_OPTIONALITY = "conflict.originalOptionality";
77
78 private final VersionSelector versionSelector;
79
80 private final ScopeSelector scopeSelector;
81
82 private final ScopeDeriver scopeDeriver;
83
84 private final OptionalitySelector optionalitySelector;
85
86
87
88
89
90
91
92
93
94 public ConflictResolver( VersionSelector versionSelector, ScopeSelector scopeSelector,
95 OptionalitySelector optionalitySelector, ScopeDeriver scopeDeriver )
96 {
97 if ( versionSelector == null )
98 {
99 throw new IllegalArgumentException( "version selector not specified" );
100 }
101 this.versionSelector = versionSelector;
102 if ( scopeSelector == null )
103 {
104 throw new IllegalArgumentException( "scope selector not specified" );
105 }
106 this.scopeSelector = scopeSelector;
107 if ( scopeDeriver == null )
108 {
109 throw new IllegalArgumentException( "scope deriver not specified" );
110 }
111 this.scopeDeriver = scopeDeriver;
112 if ( optionalitySelector == null )
113 {
114 throw new IllegalArgumentException( "optionality selector not specified" );
115 }
116 this.optionalitySelector = optionalitySelector;
117 }
118
119 public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
120 throws RepositoryException
121 {
122 List<?> sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
123 if ( sortedConflictIds == null )
124 {
125 ConflictIdSorter sorter = new ConflictIdSorter();
126 sorter.transformGraph( node, context );
127
128 sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
129 }
130
131
132
133
134
135 @SuppressWarnings( "unchecked" )
136 Collection<Collection<?>> conflictIdCycles =
137 (Collection<Collection<?>>) context.get( TransformationContextKeys.CYCLIC_CONFLICT_IDS );
138 if ( conflictIdCycles == null )
139 {
140 throw new RepositoryException( "conflict id cycles have not been identified" );
141 }
142
143 Map<?, ?> conflictIds = (Map<?, ?>) context.get( TransformationContextKeys.CONFLICT_IDS );
144 if ( conflictIds == null )
145 {
146 throw new RepositoryException( "conflict groups have not been identified" );
147 }
148
149 Map<Object, Collection<Object>> cyclicPredecessors = new HashMap<Object, Collection<Object>>();
150 for ( Collection<?> cycle : conflictIdCycles )
151 {
152 for ( Object conflictId : cycle )
153 {
154 Collection<Object> predecessors = cyclicPredecessors.get( conflictId );
155 if ( predecessors == null )
156 {
157 predecessors = new HashSet<Object>();
158 cyclicPredecessors.put( conflictId, predecessors );
159 }
160 predecessors.addAll( cycle );
161 }
162 }
163
164 State state = new State( node, conflictIds, sortedConflictIds.size(), context );
165 for ( Iterator<?> it = sortedConflictIds.iterator(); it.hasNext(); )
166 {
167 Object conflictId = it.next();
168
169
170 state.prepare( conflictId, cyclicPredecessors.get( conflictId ) );
171
172
173 gatherConflictItems( node, state );
174
175
176 state.finish();
177
178
179 if ( !state.items.isEmpty() )
180 {
181 ConflictContext ctx = state.conflictCtx;
182 state.versionSelector.selectVersion( ctx );
183 if ( ctx.winner == null )
184 {
185 throw new RepositoryException( "conflict resolver did not select winner among " + state.items );
186 }
187 DependencyNode winner = ctx.winner.node;
188
189 state.scopeSelector.selectScope( ctx );
190 if ( state.verbose )
191 {
192 winner.setData( NODE_DATA_ORIGINAL_SCOPE, winner.getDependency().getScope() );
193 }
194 winner.setScope( ctx.scope );
195
196 state.optionalitySelector.selectOptionality( ctx );
197 if ( state.verbose )
198 {
199 winner.setData( NODE_DATA_ORIGINAL_OPTIONALITY, winner.getDependency().isOptional() );
200 }
201 winner.getDependency().setOptional( ctx.optional );
202
203
204 removeLosers( state );
205 }
206
207
208 state.winner();
209
210
211 if ( !it.hasNext() && !conflictIdCycles.isEmpty() && state.conflictCtx.winner != null )
212 {
213 DependencyNode winner = state.conflictCtx.winner.node;
214 state.prepare( state, null );
215 gatherConflictItems( winner, state );
216 }
217 }
218
219
220
221
222
223
224
225
226 return node;
227 }
228
229 private boolean gatherConflictItems( DependencyNode node, State state )
230 throws RepositoryException
231 {
232 Object conflictId = state.conflictIds.get( node );
233 if ( state.currentId.equals( conflictId ) )
234 {
235
236 state.add( node );
237
238 }
239 else if ( state.loser( node, conflictId ) )
240 {
241
242 return false;
243 }
244 else if ( state.push( node, conflictId ) )
245 {
246
247 for ( Iterator<DependencyNode> it = node.getChildren().iterator(); it.hasNext(); )
248 {
249 DependencyNode child = it.next();
250 if ( !gatherConflictItems( child, state ) )
251 {
252 it.remove();
253 }
254 }
255 state.pop();
256 }
257 return true;
258 }
259
260 private void removeLosers( State state )
261 {
262 ConflictItem winner = state.conflictCtx.winner;
263 List<DependencyNode> previousParent = null;
264 ListIterator<DependencyNode> childIt = null;
265 boolean conflictVisualized = false;
266 for ( ConflictItem item : state.items )
267 {
268 if ( item == winner )
269 {
270 continue;
271 }
272 if ( item.parent != previousParent )
273 {
274 childIt = item.parent.listIterator();
275 previousParent = item.parent;
276 conflictVisualized = false;
277 }
278 while ( childIt.hasNext() )
279 {
280 DependencyNode child = childIt.next();
281 if ( child == item.node )
282 {
283 if ( state.verbose && !conflictVisualized && item.parent != winner.parent )
284 {
285 conflictVisualized = true;
286 DependencyNode loser = new DefaultDependencyNode( child );
287 loser.setData( NODE_DATA_WINNER, winner.node );
288 loser.setData( NODE_DATA_ORIGINAL_SCOPE, loser.getDependency().getScope() );
289 loser.setData( NODE_DATA_ORIGINAL_OPTIONALITY, loser.getDependency().isOptional() );
290 loser.setScope( item.getScopes().iterator().next() );
291
292 childIt.set( loser );
293 }
294 else
295 {
296 childIt.remove();
297 }
298 break;
299 }
300 }
301 }
302
303
304 }
305
306 final class NodeInfo
307 {
308
309
310
311
312 int minDepth;
313
314
315
316
317
318
319 Object derivedScopes;
320
321
322
323
324
325
326 int derivedOptionalities;
327
328
329
330
331
332 List<ConflictItem> children;
333
334 static final int CHANGE_SCOPE = 0x01;
335
336 static final int CHANGE_OPTIONAL = 0x02;
337
338 private static final int OPT_FALSE = 0x01;
339
340 private static final int OPT_TRUE = 0x02;
341
342 NodeInfo( int depth, String derivedScope, boolean optional )
343 {
344 minDepth = depth;
345 derivedScopes = derivedScope;
346 derivedOptionalities = optional ? OPT_TRUE : OPT_FALSE;
347 }
348
349 @SuppressWarnings( "unchecked" )
350 int update( int depth, String derivedScope, boolean optional )
351 {
352 if ( depth < minDepth )
353 {
354 minDepth = depth;
355 }
356 int changes;
357 if ( derivedScopes.equals( derivedScope ) )
358 {
359 changes = 0;
360 }
361 else if ( derivedScopes instanceof Collection )
362 {
363 changes = ( (Collection<String>) derivedScopes ).add( derivedScope ) ? CHANGE_SCOPE : 0;
364 }
365 else
366 {
367 Collection<String> scopes = new HashSet<String>();
368 scopes.add( (String) derivedScopes );
369 scopes.add( derivedScope );
370 derivedScopes = scopes;
371 changes = CHANGE_SCOPE;
372 }
373 int bit = optional ? OPT_TRUE : OPT_FALSE;
374 if ( ( derivedOptionalities & bit ) == 0 )
375 {
376 derivedOptionalities |= bit;
377 changes |= CHANGE_OPTIONAL;
378 }
379 return changes;
380 }
381
382 void add( ConflictItem item )
383 {
384 if ( children == null )
385 {
386 children = new ArrayList<ConflictItem>( 1 );
387 }
388 children.add( item );
389 }
390
391 }
392
393 final class State
394 {
395
396
397
398
399 Object currentId;
400
401
402
403
404 int totalConflictItems;
405
406
407
408
409 final boolean verbose;
410
411
412
413
414
415 final Map<Object, DependencyNode> resolvedIds;
416
417
418
419
420
421
422 final Collection<Object> potentialAncestorIds;
423
424
425
426
427 final Map<?, ?> conflictIds;
428
429
430
431
432 final List<ConflictItem> items;
433
434
435
436
437
438 final Map<List<DependencyNode>, NodeInfo> infos;
439
440
441
442
443
444 final Map<List<DependencyNode>, Object> stack;
445
446
447
448
449 final List<DependencyNode> parentNodes;
450
451
452
453
454 final List<String> parentScopes;
455
456
457
458
459 final List<Boolean> parentOptionals;
460
461
462
463
464
465 final List<NodeInfo> parentInfos;
466
467
468
469
470
471 final ConflictContext conflictCtx;
472
473
474
475
476
477 final ScopeContext scopeCtx;
478
479
480
481
482 final VersionSelector versionSelector;
483
484
485
486
487 final ScopeSelector scopeSelector;
488
489
490
491
492 final ScopeDeriver scopeDeriver;
493
494
495
496
497 final OptionalitySelector optionalitySelector;
498
499 State( DependencyNode root, Map<?, ?> conflictIds, int conflictIdCount,
500 DependencyGraphTransformationContext context )
501 throws RepositoryException
502 {
503 this.conflictIds = conflictIds;
504 verbose = ConfigUtils.getBoolean( context.getSession(), false, CONFIG_PROP_VERBOSE );
505 potentialAncestorIds = new HashSet<Object>( conflictIdCount * 2 );
506 resolvedIds = new HashMap<Object, DependencyNode>( conflictIdCount * 2 );
507 items = new ArrayList<ConflictItem>( 256 );
508 infos = new IdentityHashMap<List<DependencyNode>, NodeInfo>( 64 );
509 stack = new IdentityHashMap<List<DependencyNode>, Object>( 64 );
510 parentNodes = new ArrayList<DependencyNode>( 64 );
511 parentScopes = new ArrayList<String>( 64 );
512 parentOptionals = new ArrayList<Boolean>( 64 );
513 parentInfos = new ArrayList<NodeInfo>( 64 );
514 conflictCtx = new ConflictContext( root, conflictIds, items );
515 scopeCtx = new ScopeContext( null, null );
516 versionSelector = ConflictResolver.this.versionSelector.getInstance( root, context );
517 scopeSelector = ConflictResolver.this.scopeSelector.getInstance( root, context );
518 scopeDeriver = ConflictResolver.this.scopeDeriver.getInstance( root, context );
519 optionalitySelector = ConflictResolver.this.optionalitySelector.getInstance( root, context );
520 }
521
522 void prepare( Object conflictId, Collection<Object> cyclicPredecessors )
523 {
524 currentId = conflictId;
525 conflictCtx.conflictId = conflictId;
526 conflictCtx.winner = null;
527 conflictCtx.scope = null;
528 conflictCtx.optional = null;
529 items.clear();
530 infos.clear();
531 if ( cyclicPredecessors != null )
532 {
533 potentialAncestorIds.addAll( cyclicPredecessors );
534 }
535 }
536
537 void finish()
538 {
539 List<DependencyNode> previousParent = null;
540 int previousDepth = 0;
541 totalConflictItems += items.size();
542 for ( int i = items.size() - 1; i >= 0; i-- )
543 {
544 ConflictItem item = items.get( i );
545 if ( item.parent == previousParent )
546 {
547 item.depth = previousDepth;
548 }
549 else if ( item.parent != null )
550 {
551 previousParent = item.parent;
552 NodeInfo info = infos.get( previousParent );
553 previousDepth = info.minDepth + 1;
554 item.depth = previousDepth;
555 }
556 }
557 potentialAncestorIds.add( currentId );
558 }
559
560 void winner()
561 {
562 resolvedIds.put( currentId, ( conflictCtx.winner != null ) ? conflictCtx.winner.node : null );
563 }
564
565 boolean loser( DependencyNode node, Object conflictId )
566 {
567 DependencyNode winner = resolvedIds.get( conflictId );
568 return winner != null && winner != node;
569 }
570
571 boolean push( DependencyNode node, Object conflictId )
572 throws RepositoryException
573 {
574 if ( conflictId == null )
575 {
576 if ( node.getDependency() != null )
577 {
578 if ( node.getData().get( NODE_DATA_WINNER ) != null )
579 {
580 return false;
581 }
582 throw new RepositoryException( "missing conflict id for node " + node );
583 }
584 }
585 else if ( !potentialAncestorIds.contains( conflictId ) )
586 {
587 return false;
588 }
589
590 List<DependencyNode> graphNode = node.getChildren();
591 if ( stack.put( graphNode, Boolean.TRUE ) != null )
592 {
593 return false;
594 }
595
596 int depth = depth();
597 String scope = deriveScope( node, conflictId );
598 boolean optional = deriveOptional( node, conflictId );
599 NodeInfo info = infos.get( graphNode );
600 if ( info == null )
601 {
602 info = new NodeInfo( depth, scope, optional );
603 infos.put( graphNode, info );
604 parentInfos.add( info );
605 parentNodes.add( node );
606 parentScopes.add( scope );
607 parentOptionals.add( optional );
608 }
609 else
610 {
611 int changes = info.update( depth, scope, optional );
612 if ( changes == 0 )
613 {
614 stack.remove( graphNode );
615 return false;
616 }
617 parentInfos.add( null );
618 parentNodes.add( node );
619 parentScopes.add( scope );
620 parentOptionals.add( optional );
621 if ( info.children != null )
622 {
623 if ( ( changes & NodeInfo.CHANGE_SCOPE ) != 0 )
624 {
625 for ( int i = info.children.size() - 1; i >= 0; i-- )
626 {
627 ConflictItem item = info.children.get( i );
628 String childScope = deriveScope( item.node, null );
629 item.addScope( childScope );
630 }
631 }
632 if ( ( changes & NodeInfo.CHANGE_OPTIONAL ) != 0 )
633 {
634 for ( int i = info.children.size() - 1; i >= 0; i-- )
635 {
636 ConflictItem item = info.children.get( i );
637 boolean childOptional = deriveOptional( item.node, null );
638 item.addOptional( childOptional );
639 }
640 }
641 }
642 }
643
644 return true;
645 }
646
647 void pop()
648 {
649 int last = parentInfos.size() - 1;
650 parentInfos.remove( last );
651 parentScopes.remove( last );
652 parentOptionals.remove( last );
653 DependencyNode node = parentNodes.remove( last );
654 stack.remove( node.getChildren() );
655 }
656
657 void add( DependencyNode node )
658 throws RepositoryException
659 {
660 DependencyNode parent = parent();
661 if ( parent == null )
662 {
663 ConflictItem item = newConflictItem( parent, node );
664 items.add( item );
665 }
666 else
667 {
668 NodeInfo info = parentInfos.get( parentInfos.size() - 1 );
669 if ( info != null )
670 {
671 ConflictItem item = newConflictItem( parent, node );
672 info.add( item );
673 items.add( item );
674 }
675 }
676 }
677
678 private ConflictItem newConflictItem( DependencyNode parent, DependencyNode node )
679 throws RepositoryException
680 {
681 return new ConflictItem( parent, node, deriveScope( node, null ), deriveOptional( node, null ) );
682 }
683
684 private int depth()
685 {
686 return parentNodes.size();
687 }
688
689 private DependencyNode parent()
690 {
691 int size = parentNodes.size();
692 return ( size <= 0 ) ? null : parentNodes.get( size - 1 );
693 }
694
695 private String deriveScope( DependencyNode node, Object conflictId )
696 throws RepositoryException
697 {
698 if ( node.getPremanagedScope() != null
699 || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
700
701
702 {
703 return scope( node.getDependency() );
704 }
705
706 int depth = parentNodes.size();
707 scopes( depth, node.getDependency() );
708 if ( depth > 0 )
709 {
710 scopeDeriver.deriveScope( scopeCtx );
711 }
712 return scopeCtx.derivedScope;
713 }
714
715 private void scopes( int parent, Dependency child )
716 {
717 scopeCtx.parentScope = ( parent > 0 ) ? parentScopes.get( parent - 1 ) : null;
718 scopeCtx.derivedScope = scope( child );
719 scopeCtx.childScope = scopeCtx.derivedScope;
720 }
721
722 private String scope( Dependency dependency )
723 {
724 return ( dependency != null ) ? dependency.getScope() : null;
725 }
726
727 private boolean deriveOptional( DependencyNode node, Object conflictId )
728 {
729 Dependency dep = node.getDependency();
730 boolean optional = ( dep != null ) ? dep.isOptional() : false;
731 if ( optional
732 || ( node.getData().get( NODE_DATA_ORIGINAL_OPTIONALITY ) != null
733 && ( (Boolean) node.getData().get( NODE_DATA_ORIGINAL_OPTIONALITY ) ).booleanValue() )
734 || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
735
736
737 {
738 return optional;
739 }
740 int depth = parentNodes.size();
741 return ( depth > 0 ) ? parentOptionals.get( depth - 1 ) : false;
742 }
743
744 }
745
746
747
748
749
750
751
752
753 public static final class ScopeContext
754 {
755
756 String parentScope;
757
758 String childScope;
759
760 String derivedScope;
761
762
763
764
765
766
767
768
769
770 public ScopeContext( String parentScope, String childScope )
771 {
772 this.parentScope = ( parentScope != null ) ? parentScope : "";
773 derivedScope = ( childScope != null ) ? childScope : "";
774 this.childScope = derivedScope;
775 }
776
777
778
779
780
781
782
783 public String getParentScope()
784 {
785 return parentScope;
786 }
787
788
789
790
791
792
793
794 public String getChildScope()
795 {
796 return childScope;
797 }
798
799
800
801
802
803
804
805 public String getDerivedScope()
806 {
807 return derivedScope;
808 }
809
810
811
812
813
814
815 public void setDerivedScope( String derivedScope )
816 {
817 this.derivedScope = ( derivedScope != null ) ? derivedScope : "";
818 }
819
820 }
821
822
823
824
825
826
827
828 public static final class ConflictItem
829 {
830
831
832 final List<DependencyNode> parent;
833
834
835 final Artifact artifact;
836
837 final DependencyNode node;
838
839 int depth;
840
841
842 Object scopes;
843
844
845 int optionalities;
846
847
848
849
850 public static final int OPTIONAL_FALSE = 0x01;
851
852
853
854
855 public static final int OPTIONAL_TRUE = 0x02;
856
857 ConflictItem( DependencyNode parent, DependencyNode node, String scope, boolean optional )
858 {
859 if ( parent != null )
860 {
861 this.parent = parent.getChildren();
862 this.artifact = parent.getDependency().getArtifact();
863
864 }
865 else
866 {
867 this.parent = null;
868 this.artifact = null;
869 }
870 this.node = node;
871 this.scopes = scope;
872 this.optionalities = optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888 public ConflictItem( DependencyNode parent, DependencyNode node, int depth, int optionalities,
889 String... scopes )
890 {
891 this.parent = ( parent != null ) ? parent.getChildren() : null;
892 this.artifact = ( parent != null ) ? parent.getDependency().getArtifact() : null;
893
894 this.node = node;
895 this.depth = depth;
896 this.optionalities = optionalities;
897 this.scopes = Arrays.asList( scopes );
898 }
899
900
901
902
903
904
905
906 public boolean isSibling( ConflictItem item )
907 {
908 return parent == item.parent;
909 }
910
911
912
913
914
915
916 public DependencyNode getNode()
917 {
918 return node;
919 }
920
921
922
923
924
925
926 public Dependency getDependency()
927 {
928 return node.getDependency();
929 }
930
931
932
933
934
935
936
937
938 public int getDepth()
939 {
940 return depth;
941 }
942
943
944
945
946
947
948
949
950 @SuppressWarnings( "unchecked" )
951 public Collection<String> getScopes()
952 {
953 if ( scopes instanceof String )
954 {
955 return Collections.singleton( (String) scopes );
956 }
957 return (Collection<String>) scopes;
958 }
959
960 @SuppressWarnings( "unchecked" )
961 void addScope( String scope )
962 {
963 if ( scopes instanceof Collection )
964 {
965 ( (Collection<String>) scopes ).add( scope );
966 }
967 else if ( !scopes.equals( scope ) )
968 {
969 Collection<Object> set = new HashSet<Object>();
970 set.add( scopes );
971 set.add( scope );
972 scopes = set;
973 }
974 }
975
976
977
978
979
980
981
982
983
984 public int getOptionalities()
985 {
986 return optionalities;
987 }
988
989 void addOptional( boolean optional )
990 {
991 optionalities |= optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
992 }
993
994 @Override
995 public String toString()
996 {
997 return node + " @ " + depth + " < " + artifact;
998 }
999
1000 }
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 public static final class ConflictContext
1011 {
1012
1013 final DependencyNode root;
1014
1015 final Map<?, ?> conflictIds;
1016
1017 final Collection<ConflictItem> items;
1018
1019 Object conflictId;
1020
1021 ConflictItem winner;
1022
1023 String scope;
1024
1025 Boolean optional;
1026
1027 ConflictContext( DependencyNode root, Map<?, ?> conflictIds, Collection<ConflictItem> items )
1028 {
1029 this.root = root;
1030 this.conflictIds = conflictIds;
1031 this.items = Collections.unmodifiableCollection( items );
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 public ConflictContext( DependencyNode root, Object conflictId, Map<DependencyNode, Object> conflictIds,
1046 Collection<ConflictItem> items )
1047 {
1048 this( root, conflictIds, items );
1049 this.conflictId = conflictId;
1050 }
1051
1052
1053
1054
1055
1056
1057 public DependencyNode getRoot()
1058 {
1059 return root;
1060 }
1061
1062
1063
1064
1065
1066
1067
1068 public boolean isIncluded( DependencyNode node )
1069 {
1070 return conflictId.equals( conflictIds.get( node ) );
1071 }
1072
1073
1074
1075
1076
1077
1078 public Collection<ConflictItem> getItems()
1079 {
1080 return items;
1081 }
1082
1083
1084
1085
1086
1087
1088 public ConflictItem getWinner()
1089 {
1090 return winner;
1091 }
1092
1093
1094
1095
1096
1097
1098 public void setWinner( ConflictItem winner )
1099 {
1100 this.winner = winner;
1101 }
1102
1103
1104
1105
1106
1107
1108 public String getScope()
1109 {
1110 return scope;
1111 }
1112
1113
1114
1115
1116
1117
1118 public void setScope( String scope )
1119 {
1120 this.scope = scope;
1121 }
1122
1123
1124
1125
1126
1127
1128 public Boolean getOptional()
1129 {
1130 return optional;
1131 }
1132
1133
1134
1135
1136
1137
1138 public void setOptional( Boolean optional )
1139 {
1140 this.optional = optional;
1141 }
1142
1143 @Override
1144 public String toString()
1145 {
1146 return winner + " @ " + scope + " < " + items;
1147 }
1148
1149 }
1150
1151
1152
1153
1154
1155
1156
1157 public abstract static class VersionSelector
1158 {
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 public VersionSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
1175 throws RepositoryException
1176 {
1177 return this;
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189 public abstract void selectVersion( ConflictContext context )
1190 throws RepositoryException;
1191
1192 }
1193
1194
1195
1196
1197
1198
1199 public abstract static class ScopeSelector
1200 {
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216 public ScopeSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
1217 throws RepositoryException
1218 {
1219 return this;
1220 }
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231 public abstract void selectScope( ConflictContext context )
1232 throws RepositoryException;
1233
1234 }
1235
1236
1237
1238
1239
1240 public abstract static class ScopeDeriver
1241 {
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257 public ScopeDeriver getInstance( DependencyNode root, DependencyGraphTransformationContext context )
1258 throws RepositoryException
1259 {
1260 return this;
1261 }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271 public abstract void deriveScope( ScopeContext context )
1272 throws RepositoryException;
1273
1274 }
1275
1276
1277
1278
1279
1280
1281 public abstract static class OptionalitySelector
1282 {
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 public OptionalitySelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
1299 throws RepositoryException
1300 {
1301 return this;
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 public abstract void selectOptionality( ConflictContext context )
1314 throws RepositoryException;
1315
1316 }
1317
1318 }