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