private void resolve(GhidraBundle toResolve,
				Map<GhidraBundle, Set<GhidraBundle>> newFront) {
			List<BundleRequirement> requirements;
			try {
				List<BundleRequirement> bundleRequirements = toResolve.getAllRequirements();
				if (bundleRequirements.isEmpty()) {
					return; // no dependencies to resolve
				}
				requirements = new ArrayList<>(bundleRequirements);
			}
			catch (GhidraBundleException e) {
				fireBundleException(e);
				removeVertex(toResolve);
				return;
			}

			for (GhidraBundle supplierBundle : availableBundles) {
				for (BundleCapability capability : capabilityMap.get(supplierBundle)) {
					if (monitor.isCancelled()) {
						return;
					}
					Iterator<BundleRequirement> it = requirements.iterator();
					while (it.hasNext()) {
						BundleRequirement req = it.next();
						if (req.matches(capability)) {
							newFront.computeIfAbsent(supplierBundle, b -> new HashSet<>())
									.add(toResolve);
							it.remove();
						}
					}
					if (requirements.isEmpty()) {
						return;
					}
				}
			}

			// If requirements remain, some will be resolved by system and others will generate 
			// helpful errors for the user during activation
		}
Utility class to build a dependency graph from bundles where capabilities map to 
requirements.
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java