Files
SAE32_2024/src/fr/monlouyan/bakefile/DependencyResolver.java

110 lines
3.6 KiB
Java

package fr.monlouyan.bakefile;
import java.util.*;
public class DependencyResolver {
private boolean debug;
private Map<String, Rule> ruleMap;
private boolean isCircular;
public DependencyResolver(boolean debug) {
this.debug = debug;
this.isCircular = false;
}
public List<Rule> resolve(List<Rule> allRules, List<String> requestedRules) {
List<Rule> rulesToBuild = new ArrayList<>();
ruleMap = new HashMap<>();
// Construire la map des règles
for (Rule rule : allRules) {
ruleMap.put(rule.getName(), rule);
}
// Premier passage : détection et suppression des cycles
Set<String> visited = new HashSet<>();
Set<String> stack = new HashSet<>();
List<String> targetRules = requestedRules.isEmpty() ?
Collections.singletonList(BakefileParser.getFirstTarget()) :
requestedRules;
for (String ruleName : targetRules) {
if (ruleMap.containsKey(ruleName)) {
detectCycle(ruleName, visited, stack, ruleName);
} else if (debug) {
System.out.println("Warning: Rule '" + ruleName + "' not found.");
}
}
// Deuxième passage : collecte des dépendances dans l'ordre
Set<String> processed = new HashSet<>();
List<String> buildOrder = new ArrayList<>();
for (String ruleName : targetRules) {
topologicalSort(ruleName, processed, buildOrder);
}
// Construire la liste finale des règles dans l'ordre
for (String ruleName : buildOrder) {
Rule rule = ruleMap.get(ruleName);
if (rule != null) {
rulesToBuild.add(rule);
}
}
return rulesToBuild;
}
private void topologicalSort(String ruleName, Set<String> processed, List<String> buildOrder) {
if (!ruleMap.containsKey(ruleName) || processed.contains(ruleName)) {
return;
}
processed.add(ruleName);
Rule rule = ruleMap.get(ruleName);
// D'abord traiter les dépendances
for (String dep : rule.getDependencies()) {
topologicalSort(dep, processed, buildOrder);
}
// Puis ajouter la règle courante
buildOrder.add(ruleName);
}
// La méthode detectCycle reste inchangée
private void detectCycle(String ruleName, Set<String> visited, Set<String> stack, String parent) {
if (stack.contains(ruleName)) {
if (parent != null) {
System.out.println("bake: Circular " + parent + " <- " + ruleName + " dependency dropped.");
this.isCircular = true;
Rule parentRule = ruleMap.get(parent);
if (parentRule != null) {
parentRule.getDependencies().remove(ruleName);
}
}
return;
}
if (!visited.contains(ruleName)) {
visited.add(ruleName);
stack.add(ruleName);
Rule rule = ruleMap.get(ruleName);
if (rule != null) {
List<String> dependenciesCopy = new ArrayList<>(rule.getDependencies());
for (String dependency : dependenciesCopy) {
if (ruleMap.containsKey(dependency)) {
detectCycle(dependency, visited, stack, ruleName);
}
}
}
stack.remove(ruleName);
}
}
public boolean isCircular() {
return isCircular;
}
}