//This product is provided under the terms of EPL (Eclipse Public License) //version 1.0. // //The full license text can be read from: http://www.eclipse.org/org/documents/epl-v10.php package org.dtangler.core.analysis; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.dtangler.core.analysisresult.Violation; import org.dtangler.core.dependencies.Dependable; import org.dtangler.core.dependencies.Dependencies; import org.dtangler.core.dependencies.Dependency; public class ChildViolationFinder { private final Dependencies dependencies; public ChildViolationFinder(Dependencies dependencies) { this.dependencies = dependencies; } public Map<Dependable, Set<Violation>> findChildViolationsForParents( Map<Dependency, Set<Violation>> violationMap) { Set<Violation> allViolations = new HashSet(); for (Set<Violation> violations : violationMap.values()) allViolations.addAll(violations); Map<Dependable, Set<Violation>> result = new HashMap(); for (Violation v : allViolations) { if (violationMembersHaveSingleParent(v)) { addChildViolations(result, v); } } return result; } private void addChildViolations(Map<Dependable, Set<Violation>> result, Violation violation) { Map<Dependable, Set<Violation>> newViolations = createChildViolationsForParents( violation, violation.getMembers()); for (Dependable dep : newViolations.keySet()) { Set<Violation> oldViolations = result.get(dep); if (oldViolations == null) { oldViolations = new HashSet(); } oldViolations.addAll(newViolations.get(dep)); result.put(dep, oldViolations); } } private boolean violationMembersHaveSingleParent(Violation violation) { Dependable firstParent = null; for (Dependable member : violation.getMembers()) { Dependable parent = getParent(member); if (parent == null) return false; if (firstParent == null) firstParent = parent; else if (!firstParent.equals(parent)) return false; } return true; } private Dependable getParent(Dependable dependable) { Set<Dependable> parents = getParents(dependable); if (parents.size() != 1) // Handling multiparent relationships requires new story return null; return parents.iterator().next(); } private Set<Dependable> getParents(Dependable dependable) { return dependencies.getParents(dependable, dependencies .getParentScope(dependable.getScope())); } private Map<Dependable, Set<Violation>> createChildViolationsForParents( Violation v, Set<Dependable> items) { if (items.isEmpty()) return Collections.EMPTY_MAP; Set<Dependable> parents = new HashSet(); for (Dependable item : items) parents.addAll(getParents(item)); Map<Dependable, Set<Violation>> result = new HashMap(); for (Dependable parent : parents) createChildViolation(parent, v, result); result.putAll(createChildViolationsForParents(v, parents)); return result; } private void createChildViolation(Dependable parent, Violation v, Map<Dependable, Set<Violation>> violationMap) { Set<Violation> violations = violationMap.get(parent); if (violations == null) { violations = new HashSet(); violationMap.put(parent, violations); } violations.add(createChildViolation(parent, v)); } private Violation createChildViolation(final Dependable parent, final Violation v) { return new ChildViolation(parent, v); } }