/** * Adds an exact dependency to the give package if it is not already contained in the given list. * @param deps the original dependencies * @param id the id to add * @return the new array of dependencies, or {@code deps} if nothing changed. */ public static Dependency[] addExact(@Nonnull Dependency[] deps, @Nonnull PackageId id) { if (matches(deps, id)) { return deps; } Dependency[] newDeps = new Dependency[deps.length + 1]; System.arraycopy(deps, 0, newDeps, 0, deps.length); newDeps[deps.length] = new Dependency(id); return newDeps; }
/** * Resolves a list of resolutions respecting their internal dependency references. * @param list list of resolutions * @return a new list of resolutions * @throws CyclicDependencyException if a cyclic dependency is detected */ public static List<PackageId> resolve(Map<PackageId, Dependency[]> list) throws CyclicDependencyException { // create fake deplist Dependency[] fake = new Dependency[list.size()]; int i=0; for (Map.Entry<PackageId, Dependency[]> entry: list.entrySet()) { fake[i++] = new Dependency(entry.getKey()); } Map<PackageId, Boolean> result = new LinkedHashMap<PackageId, Boolean>(list.size()); resolve(fake, list, result); return new ArrayList<PackageId>(result.keySet()); }
Dependency[] newDeps = DependencyUtil.addExact(oldDeps, pack.getId()); if (oldDeps != newDeps) { def.setDependencies(newDeps, false); DependencyUtil.sortPackages(subPacks); } catch (CyclicDependencyException e) { if (opts.isStrict()) {
private static void resolve(Dependency[] deps, Map<PackageId, Dependency[]> list, Map<PackageId, Boolean> result) throws CyclicDependencyException { // find the dep in the list for (Dependency dep: deps) { for (Map.Entry<PackageId, Dependency[]> entry: list.entrySet()) { PackageId id = entry.getKey(); if (dep.matches(id)) { Boolean res = result.get(id); if (res != null && !res) { log.error("Package dependencies cause cycle."); throw new CyclicDependencyException(); } else if (res == null) { result.put(id, res = false); } resolve(entry.getValue(), list, result); // shove at the end of the list if not resolved if (!res) { result.remove(id); result.put(id, true); } } } } }
/** * Sorts the packages by the dependency order * @param packages packages to sort * @param <T> Type of the collection. * @throws CyclicDependencyException if a cyclic dependency is detected */ public static <T extends VaultPackage> void sort(Collection<T> packages) throws CyclicDependencyException { Map<PackageId, Dependency[]> list = new LinkedHashMap<PackageId, Dependency[]>(); Map<PackageId, VaultPackage> byId = new LinkedHashMap<PackageId, VaultPackage>(); for (VaultPackage pack: packages) { list.put(pack.getId(), pack.getDependencies()); byId.put(pack.getId(), pack); } packages.clear(); for (PackageId id: resolve(list)) { packages.add((T) byId.remove(id)); } }
/** * Sorts the packages by the dependency order * @param packages packages to sort * @param <T> Type of the collection. * @throws CyclicDependencyException if a cyclic dependency is detected * @throws javax.jcr.RepositoryException if an repository error occurs */ public static <T extends JcrPackage> void sortPackages(Collection<T> packages) throws CyclicDependencyException, RepositoryException { Map<PackageId, Dependency[]> list = new LinkedHashMap<PackageId, Dependency[]>(); Map<PackageId, JcrPackage> byId = new LinkedHashMap<PackageId, JcrPackage>(); for (JcrPackage pack: packages) { PackageId id = pack.getDefinition().getId(); list.put(id, pack.getDefinition().getDependencies()); byId.put(id, pack); } packages.clear(); for (PackageId id: resolve(list)) { packages.add((T) byId.remove(id)); } }