Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 570132408067811e234d1b51ef0c7db689e6639f (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
/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.internal.p2.director;

import java.util.*;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.osgi.service.resolver.VersionRange;

//The pickers goal is to find an installable unit that satisfies a search criteria 
//TODO we may need additional variations of these method where version can be null, or where the search returns all the match, not just the first one
//TODO do we want a facility to limit the searching space, or do we assume that the unitsToPickFrom has already been scoped 
public class Picker {
	//TODO we'll likely need better indexing capabilities
	private IInstallableUnit[] preferredSet;
	private IInstallableUnit[] completeSet;
	private IInstallableUnit[] secondChoiceSet;
	private RecommendationDescriptor recommendations;

	private List filters;

	public Picker(IInstallableUnit[] unitsToPickFrom, RecommendationDescriptor recommendations) {
		if (unitsToPickFrom != null)
			completeSet = unitsToPickFrom;
		else
			completeSet = new IInstallableUnit[0];
		this.secondChoiceSet = completeSet;
		this.recommendations = recommendations;
		this.filters = new ArrayList(2);
	}

	public Collection[] findInstallableUnit(String id, VersionRange range, RequiredCapability searchedCapability) {
		IInstallableUnit[][] tmp = findInstallableUnit(id, range, new RequiredCapability[] {searchedCapability}, false);
		return new Collection[] {Arrays.asList(tmp[0]), Arrays.asList(tmp[1])};
	}

	public void prefer(Collection filtersToAdd) {
		if (!filters.addAll(filtersToAdd))
			return;
		if (filters.size() == 0)
			return;
		Set preferredIUs = new HashSet(completeSet.length);
		Set secondChoice = new HashSet(completeSet.length);
		for (int i = 0; i < completeSet.length; i++) {
			for (Iterator iterator = filters.iterator(); iterator.hasNext();) {
				if (((IUFilter) iterator.next()).accept(completeSet[i])) {
					preferredIUs.add(completeSet[i]);
					continue;
				} else {
					secondChoice.add(completeSet[i]);
				}
			}
		}
		preferredSet = (IInstallableUnit[]) preferredIUs.toArray(new IInstallableUnit[preferredIUs.size()]);
		secondChoiceSet = (IInstallableUnit[]) secondChoice.toArray(new IInstallableUnit[secondChoice.size()]);
	}

	public IInstallableUnit[][] findInstallableUnit(String id, VersionRange range, RequiredCapability[] searchedCapability, boolean fragmentsOnly) {
		return new IInstallableUnit[][] {findInstallableUnit(preferredSet, id, range, searchedCapability, fragmentsOnly), findInstallableUnit(secondChoiceSet, id, range, searchedCapability, fragmentsOnly)};
	}

	//TODO what should be the return value when all the parameters are null. Is it even a valid call?
	//TODO A lot of improvement could be done on this algorithm, for example
	// - remove from the set of searchedCapability the one that are found
	private IInstallableUnit[] findInstallableUnit(IInstallableUnit[] pool, String id, VersionRange range, RequiredCapability[] searchedCapability, boolean fragmentsOnly) {
		if (pool == null || pool.length == 0)
			return new IInstallableUnit[0];
		Set candidates = new HashSet();

		//Filter on plugin id and range
		if (id != null && range != null) {
			for (int i = 0; i < pool.length; i++) {
				if (pool[i].getId().equals(id) && range.isIncluded(pool[i].getVersion()))
					candidates.add(pool[i]);
			}
			pool = (IInstallableUnit[]) candidates.toArray(new IInstallableUnit[candidates.size()]);
		}

		//Filter on capabilities.
		if (searchedCapability != null) {
			searchedCapability = rewrite(searchedCapability);
			for (int i = 0; i < pool.length; i++) {
				IInstallableUnit candidate = pool[i];
				for (int k = 0; k < searchedCapability.length; k++) {
					boolean valid = false;
					ProvidedCapability[] capabilities = candidate.getProvidedCapabilities();
					if (capabilities.length == 0)
						valid = false;
					for (int j = 0; j < capabilities.length; j++) {
						if ((searchedCapability[k].getName().equals(capabilities[j].getName()) && searchedCapability[k].getNamespace().equals(capabilities[j].getNamespace()) && (searchedCapability[k].getRange() == null ? true : searchedCapability[k].getRange().isIncluded(capabilities[j].getVersion())))) { //TODO Need to deal with option
							valid = true;
							break;
						}
					}
					if (valid && (!fragmentsOnly || candidate.isFragment())) {
						candidates.add(candidate);
					}
				}
			}
			pool = (IInstallableUnit[]) candidates.toArray(new IInstallableUnit[candidates.size()]);
		}

		return pool;
	}

	private RequiredCapability[] rewrite(RequiredCapability[] requiredCapabilities) {
		if (recommendations == null)
			return requiredCapabilities;
		RequiredCapability[] result = new RequiredCapability[requiredCapabilities.length];
		for (int i = 0; i < requiredCapabilities.length; i++) {
			result[i] = getRecommendation(requiredCapabilities[i]);
			if (result[i] == null)
				result[i] = requiredCapabilities[i];
		}
		return result;
	}

	private RequiredCapability getRecommendation(RequiredCapability match) {
		Recommendation foundRecommendation = recommendations.findRecommendation(match);
		return foundRecommendation != null ? foundRecommendation.newValue() : match;
	}
}

Back to the top