package it.unibas.lunatic.model.dependency.operators; import it.unibas.lunatic.Scenario; import it.unibas.lunatic.model.chase.commons.operators.ChaseUtility; import it.unibas.lunatic.model.dependency.Dependency; import it.unibas.lunatic.model.dependency.FormulaVariable; import it.unibas.lunatic.model.dependency.FormulaVariableOccurrence; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.jgrapht.DirectedGraph; import org.jgrapht.alg.DijkstraShortestPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import speedy.model.database.AttributeRef; public class FindAttributesWithLabeledNulls { private final static Logger logger = LoggerFactory.getLogger(FindAttributesWithLabeledNulls.class); @SuppressWarnings("unchecked") public Set<AttributeRef> findAttributes(DirectedGraph<AttributeRef, ExtendedEdge> dependencyGraph, Scenario scenario) { if (dependencyGraph == null) { return Collections.EMPTY_SET; } if (logger.isDebugEnabled()) logger.debug("Finding attributes with null in dependency graph\n" + dependencyGraph); Set<AttributeRef> initialAttributes = findInitialAttributes(scenario); if (logger.isDebugEnabled()) logger.debug("Initial attributes with nulls: " + initialAttributes); Set<AttributeRef> result = findReachableAttribuesOnGraph(initialAttributes, dependencyGraph); if (logger.isDebugEnabled()) logger.debug("Attributes with nulls: " + result); return result; } private Set<AttributeRef> findInitialAttributes(Scenario scenario) { Set<AttributeRef> initialAttributes = new HashSet<AttributeRef>(); for (Dependency stTGD : scenario.getSTTgds()) { processDependency(stTGD, initialAttributes); } for (Dependency targetTGD : scenario.getExtTGDs()) { processDependency(targetTGD, initialAttributes); } return initialAttributes; } private void processDependency(Dependency tgd, Set<AttributeRef> initialAttributes) { List<FormulaVariable> existentialVariables = DependencyUtility.getExistentialVariables(tgd); for (FormulaVariable existentialVariable : existentialVariables) { for (FormulaVariableOccurrence conclusionRelationalOccurrence : existentialVariable.getConclusionRelationalOccurrences()) { AttributeRef unaliasAttribute = ChaseUtility.unAlias(conclusionRelationalOccurrence.getAttributeRef()); initialAttributes.add(unaliasAttribute); } } } private Set<AttributeRef> findReachableAttribuesOnGraph(Set<AttributeRef> initialAttributes, DirectedGraph<AttributeRef, ExtendedEdge> dependencyGraph) { Set<AttributeRef> result = new HashSet<AttributeRef>(initialAttributes); for (AttributeRef attribute : dependencyGraph.vertexSet()) { if (result.contains(attribute)) { continue; } if (isReachable(attribute, initialAttributes, dependencyGraph)) { result.add(attribute); } } return result; } private boolean isReachable(AttributeRef attribute, Set<AttributeRef> initialAttributes, DirectedGraph<AttributeRef, ExtendedEdge> dependencyGraph) { for (AttributeRef initialAttribute : initialAttributes) { if (logger.isTraceEnabled()) logger.trace("Checking reachability of " + attribute + " from " + initialAttribute); if (!dependencyGraph.containsVertex(initialAttribute)) { continue; } List path = DijkstraShortestPath.findPathBetween(dependencyGraph, initialAttribute, attribute); if (path != null) { if (logger.isTraceEnabled()) logger.trace("Found!"); return true; } } return false; } }