package jdepend.framework; import java.util.*; import jdepend.framework.JavaPackage; /** * The <code>DependencyConstraint</code> class is a constraint that tests * whether two package-dependency graphs are equivalent. * <p> * This class is useful for writing package dependency assertions (e.g. JUnit). * For example, the following JUnit test will ensure that the 'ejb' and 'web' * packages only depend upon the 'util' package, and no others: * <p> * <blockquote> * * <pre> * * public void testDependencyConstraint() { * * JDepend jdepend = new JDepend(); * jdepend.addDirectory("/path/to/classes"); * Collection analyzedPackages = jdepend.analyze(); * * DependencyConstraint constraint = new DependencyConstraint(); * * JavaPackage ejb = constraint.addPackage("com.xyz.ejb"); * JavaPackage web = constraint.addPackage("com.xyz.web"); * JavaPackage util = constraint.addPackage("com.xyz.util"); * * ejb.dependsUpon(util); * web.dependsUpon(util); * * assertEquals("Dependency mismatch", true, constraint * .match(analyzedPackages)); * } * </pre> * * </blockquote> * </p> * * @author <b>Mike Clark</b> * @author Clarkware Consulting, Inc. */ public class DependencyConstraint { private HashMap packages; public DependencyConstraint() { packages = new HashMap(); } public JavaPackage addPackage(String packageName) { JavaPackage jPackage = (JavaPackage) packages.get(packageName); if (jPackage == null) { jPackage = new JavaPackage(packageName); addPackage(jPackage); } return jPackage; } public void addPackage(JavaPackage jPackage) { if (!packages.containsValue(jPackage)) { packages.put(jPackage.getName(), jPackage); } } public Collection getPackages() { return packages.values(); } /** * Indicates whether the specified packages match the * packages in this constraint. * * @return <code>true</code> if the packages match this constraint */ public boolean match(Collection expectedPackages) { if (packages.size() == expectedPackages.size()) { for (Iterator i = expectedPackages.iterator(); i.hasNext();) { Object next = i.next(); if (next instanceof JavaPackage) { JavaPackage nextPackage = (JavaPackage) next; if (!matchPackage(nextPackage)) { return false; } } else { break; } return true; } } return false; } private boolean matchPackage(JavaPackage expectedPackage) { JavaPackage actualPackage = (JavaPackage) packages.get(expectedPackage .getName()); if (actualPackage != null) { if (equalsDependencies(actualPackage, expectedPackage)) { return true; } } return false; } private boolean equalsDependencies(JavaPackage a, JavaPackage b) { return equalsAfferents(a, b) && equalsEfferents(a, b); } private boolean equalsAfferents(JavaPackage a, JavaPackage b) { if (a.equals(b)) { Collection otherAfferents = b.getAfferents(); if (a.getAfferents().size() == otherAfferents.size()) { for (Iterator i = a.getAfferents().iterator(); i.hasNext();) { JavaPackage afferent = (JavaPackage)i.next(); if (!otherAfferents.contains(afferent)) { return false; } } return true; } } return false; } private boolean equalsEfferents(JavaPackage a, JavaPackage b) { if (a.equals(b)) { Collection otherEfferents = b.getEfferents(); if (a.getEfferents().size() == otherEfferents.size()) { for (Iterator i = a.getEfferents().iterator(); i.hasNext();) { JavaPackage efferent = (JavaPackage)i.next(); if (!otherEfferents.contains(efferent)) { return false; } } return true; } } return false; } }