package org.openlca.ilcd.util;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.function.Consumer;
import org.openlca.ilcd.commons.IDataSet;
import org.openlca.ilcd.commons.Ref;
import org.openlca.ilcd.io.DataStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DependencyTraversal {
private final Logger log = LoggerFactory.getLogger(getClass());
private final DataStore store;
public DependencyTraversal(DataStore store) {
this.store = store;
}
/**
* Visits all data sets that are reachable from the given data set reference
* and calls the consumer function for each of these data sets including the
* data set of the start-reference.
*/
public void on(Ref start, Consumer<IDataSet> fn) {
if (store == null || start == null || fn == null)
return;
ArrayList<Ref> visited = new ArrayList<>();
ArrayDeque<Ref> deque = new ArrayDeque<>();
deque.add(start);
while (!deque.isEmpty()) {
Ref next = deque.poll();
visited.add(next);
try {
IDataSet ds = store.get(next.getDataSetClass(), next.uuid);
if (ds == null) {
log.warn("could not get data set for {}", next);
continue;
}
fn.accept(ds);
for (Ref dep : RefTree.create(ds).getRefs()) {
if (visited.contains(dep) || deque.contains(dep))
continue;
deque.add(dep);
}
} catch (Exception e) {
log.error("failed to get dependencies for {}", next, e);
}
}
}
}