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