blob: fc1bdc372afaa7a27428cf8f45550688d5fcee88 [file] [log] [blame]
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});
}
}