public void completeNodeGraph() throws GadgetException { if (!calculatedDepsStale) { return; } // Detect feature dependency loop Set<String> tempList = new HashSet<String>(); this.checkDependencyLoop(this, tempList); this.nodeDepth = 0; this.transitiveDeps = Lists.newLinkedList(); this.transitiveDeps.add(this); Queue<Pair<FeatureNode, Pair<Integer, String>>> toTraverse = Lists.newLinkedList(); toTraverse.add(Pair.of(this, Pair.of(0, ""))); while (!toTraverse.isEmpty()) { Pair<FeatureNode, Pair<Integer, String>> next = toTraverse.poll(); String debug = next.two.two + (next.two.one > 0 ? " -> " : "") + next.one.name; // Breadth-first list of dependencies. this.transitiveDeps.add(next.one); this.nodeDepth = Math.max(this.nodeDepth, next.two.one); for (FeatureNode nextDep : next.one.getDepList()) { toTraverse.add(Pair.of(nextDep, Pair.of(next.two.one + 1, debug))); } } Collections.reverse(this.transitiveDeps); calculatedDepsStale = false; }
for (FeatureNode nextDep : next.one.getDepList()) { toTraverse.add(Pair.of(nextDep, Pair.of(next.two.one + 1, debug)));
for (FeatureNode nextDep : next.one.getDepList()) { toTraverse.add(Pair.of(nextDep, Pair.of(next.two.one + 1, debug)));
/** * Check whether current feature node has dependency loop * @param featureNode * feature node which needs to check whether it has dependency loop. * @param dependencyList * used to check whether current branch of feature dependency tree has dependency loop or not. * @throws GadgetException * a new GadgetException will be thrown if a loop is detected. */ private void checkDependencyLoop(FeatureNode featureNode, Set<String> dependencyList) throws GadgetException { String featureNodeName = featureNode.name; if (dependencyList.contains(featureNodeName)) { // If dependencyList already contains this feature node, then current branch has dependency loop. throw new GadgetException(GadgetException.Code.INVALID_CONFIG, "Feature " + featureNodeName + " has dependency loop problem."); } // Add the current dependency into branch. dependencyList.add(featureNodeName); List<FeatureNode> deps = featureNode.getDepList(); for (FeatureNode f : deps) { checkDependencyLoop(f, dependencyList); // Remove the part which already has been verified. dependencyList.remove(f.name); } } }