Skip to main content
summaryrefslogtreecommitdiffstats
blob: fc1bdc372afaa7a27428cf8f45550688d5fcee88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package org.eclipse.equinox.internal.p2.engine;

import java.util.*;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.query.*;

public class OperandSorter {
	IQueryable<IInstallableUnit> allIUs;
	IInstallableUnit[] sortedIUs;
	boolean doingInstall = true;
	Operand[] operandsToSort = null;

	Map<IInstallableUnit, Operand> iuToIUOperand = new HashMap<IInstallableUnit, Operand>();
	Map<IInstallableUnit, Operand> iuToIUPropertyOperand = new HashMap<IInstallableUnit, Operand>();

	public OperandSorter(IQueryable<IInstallableUnit> allIUs, boolean installOrUninstall) {
		this.allIUs = allIUs;
		doingInstall = installOrUninstall;
	}

	private void indexOperands() {
		for (int i = 0; i < operandsToSort.length; i++) {
			if (operandsToSort[i] instanceof InstallableUnitOperand) {
				InstallableUnitOperand iuo = (InstallableUnitOperand) operandsToSort[i];
				if (iuo.first() != null)
					iuToIUOperand.put(iuo.first(), iuo);
				if (iuo.second() != null)
					iuToIUOperand.put(iuo.second(), iuo);
			}

			if (operandsToSort[i] instanceof InstallableUnitPropertyOperand) {
				InstallableUnitPropertyOperand iupo = (InstallableUnitPropertyOperand) operandsToSort[i];
				iuToIUPropertyOperand.put(iupo.getInstallableUnit(), iupo);
			}
		}
	}

	public void sortOperands(Operand[] operands) {
		operandsToSort = operands;
		sortedIUs = allIUs.query(QueryUtil.ALL_UNITS, null).toUnmodifiableSet().toArray(new IInstallableUnit[0]);
		sortIUs();
		indexOperands();
		computeInstallOrder();
		computeUninstallOrder();
	}

	private ArrayList<Operand> installOrder;
	private ArrayList<Operand> uninstallOrder;

	private void computeInstallOrder() {
		installOrder = new ArrayList<Operand>(); //TODO size
		for (int i = 0; i < sortedIUs.length; i++) {
			IInstallableUnit iInstallableUnit = sortedIUs[i];

			Operand candidate = iuToIUPropertyOperand.get(iInstallableUnit);
			if (candidate != null)
				installOrder.add(iuToIUPropertyOperand.get(iInstallableUnit));

			candidate = iuToIUOperand.get(iInstallableUnit);
			if (candidate != null)
				installOrder.add(iuToIUOperand.get(iInstallableUnit));
		}
	}

	private void computeUninstallOrder() {
		uninstallOrder = new ArrayList<Operand>(); //TODO size
		for (int i = (sortedIUs.length - 1); i != 0; i--) {
			IInstallableUnit iInstallableUnit = sortedIUs[i];

			Operand candidate = iuToIUPropertyOperand.get(iInstallableUnit);
			if (candidate != null)
				uninstallOrder.add(iuToIUPropertyOperand.get(iInstallableUnit));

			candidate = iuToIUOperand.get(iInstallableUnit);
			if (candidate != null)
				uninstallOrder.add(iuToIUOperand.get(iInstallableUnit));
		}
	}

	public ArrayList<Operand> getUninstallOrder() {
		assert (operandsToSort.length == uninstallOrder.size());
		return uninstallOrder;
	}

	public ArrayList<Operand> getInstallOrder() {
		assert (operandsToSort.length == installOrder.size());
		return installOrder;
	}

	private Object[][] sortIUs() {
		List<Object[]> references = new ArrayList<Object[]>(sortedIUs.length);
		for (int i = 0; i < sortedIUs.length; i++) {
			buildReferences(sortedIUs[i], references);
		}
		Object[][] cycles = ComputeNodeOrder.computeNodeOrder(sortedIUs, references.toArray(new Object[references.size()][]));
		if (cycles.length == 0)
			return cycles;
		//		// fix up host/fragment orders (bug 184127)
		//		for (int i = 0; i < cycles.length; i++) {
		//			for (int j = 0; j < cycles[i].length; j++) {
		//				BundleDescription fragment = (BundleDescription) cycles[i][j];
		//				if (fragment.getHost() == null)
		//					continue;
		//				BundleDescription host = (BundleDescription) fragment.getHost().getSupplier();
		//				if (host == null)
		//					continue;
		//				fixFragmentOrder(host, fragment, toSort);
		//			}
		//		}
		return cycles;
	}

	private void buildReferences(IInstallableUnit description, List<Object[]> references) {
		//TODO Do we need to deal with patches in a special way?
		//TODO Do we need to deal with fragmnets?
		//TODO Do we need to deal with 

		buildReferences(description, description.getRequirements(), references);
	}

	private void buildReferences(IInstallableUnit description, Collection<IRequirement> dependencies, List<Object[]> references) {
		for (IRequirement req : dependencies) {
			IQueryResult<IInstallableUnit> matches = allIUs.query(QueryUtil.createMatchQuery(req.getMatches()), null);
			for (Iterator<IInstallableUnit> iterator = matches.iterator(); iterator.hasNext();) {
				addReference(description, iterator.next(), references);
			}
		}
	}

	private void addReference(IInstallableUnit description, IInstallableUnit reference, List<Object[]> references) {
		// build the reference from the description
		if (description == reference || reference == null)
			return;
		references.add(new Object[] {description, reference});
	}
}

Back to the top