Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency prescription and proscription #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bin/
149 changes: 10 additions & 139 deletions src/jdepend/framework/DependencyConstraint.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,156 +5,27 @@
import jdepend.framework.JavaPackage;

/**
* The <code>DependencyConstraint</code> class is a constraint that tests
* whether two package-dependency graphs are equivalent.
* This class has been replaced by DependencyPrescription.
* <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(&quot;/path/to/classes&quot;);
* Collection analyzedPackages = jdepend.analyze();
*
* DependencyConstraint constraint = new DependencyConstraint();
*
* JavaPackage ejb = constraint.addPackage(&quot;com.xyz.ejb&quot;);
* JavaPackage web = constraint.addPackage(&quot;com.xyz.web&quot;);
* JavaPackage util = constraint.addPackage(&quot;com.xyz.util&quot;);
*
* ejb.dependsUpon(util);
* web.dependsUpon(util);
*
* assertEquals(&quot;Dependency mismatch&quot;, true, constraint
* .match(analyzedPackages));
* }
* </pre>
*
* </blockquote>
* </p>
*
* @author <b>Mike Clark</b>
* @author Clarkware Consulting, Inc.
* @deprecated use DependencyPrescription instead.
*/

public class DependencyConstraint {

private HashMap packages;

public DependencyConstraint() {
packages = new HashMap();
}

private DependencyPrescription prescription = new DependencyPrescription();

public JavaPackage addPackage(String packageName) {
JavaPackage jPackage = (JavaPackage) packages.get(packageName);
if (jPackage == null) {
jPackage = new JavaPackage(packageName);
addPackage(jPackage);
}
return jPackage;
return prescription.addPackage(packageName);
}

public void addPackage(JavaPackage jPackage) {
if (!packages.containsValue(jPackage)) {
packages.put(jPackage.getName(), jPackage);
}
}

public Collection getPackages() {
return packages.values();
prescription.addPackage(jPackage);
}

/**
* 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;
public Collection<JavaPackage> getPackages() {
return prescription.getPackages();
}

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;
public boolean match(Collection<JavaPackage> expectedPackages) {
return prescription.followsDirective(expectedPackages);
}
}
63 changes: 63 additions & 0 deletions src/jdepend/framework/DependencyDirective.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package jdepend.framework;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
* A <code>DependencyDirective</code> represents a set of dependency
* instructions to which analysed code can be compared.
* <p>
* Concrete subclasses implement the comparing functionality.
*
* @author Tom van den Berge
*/
public abstract class DependencyDirective {

protected Map<String, JavaPackage> packages = new HashMap<String, JavaPackage>();

/**
* Adds the specified package to this directive. The returned JavaPackage
* can be used to couple to other packages.
*
* @param packageName
* the name of the package.
* @return the added package.
*/
public JavaPackage addPackage(String packageName) {
JavaPackage jPackage = (JavaPackage) packages.get(packageName);
if (jPackage == null) {
jPackage = new JavaPackage(packageName);
addPackage(jPackage);
}
return jPackage;
}

/**
* Adds the specified package to this directive.
*
* @param jPackage the package to add.
*/
public void addPackage(JavaPackage jPackage) {
if (!packages.containsValue(jPackage)) {
packages.put(jPackage.getName(), jPackage);
}
}

/**
* Returns all configured packages of this directive.
*
* @return the packages.
*/
public Collection<JavaPackage> getPackages() {
return packages.values();
}

/**
* Returns true if the specified packages follow this directive.
*
* @param packages the packages to verify against this directive.
* @return true if the packages follow this directive, otherwise false.
*/
public abstract boolean followsDirective(Collection<JavaPackage> packages);
}
129 changes: 129 additions & 0 deletions src/jdepend/framework/DependencyPrescription.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package jdepend.framework;

import java.util.Collection;
import java.util.Iterator;

/**
* The <code>DependencyPrescription</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(&quot;/path/to/classes&quot;);
* Collection analyzedPackages = jdepend.analyze();
*
* DependencyPrescription constraint = new DependencyPrescription();
*
* JavaPackage ejb = constraint.addPackage(&quot;com.xyz.ejb&quot;);
* JavaPackage web = constraint.addPackage(&quot;com.xyz.web&quot;);
* JavaPackage util = constraint.addPackage(&quot;com.xyz.util&quot;);
*
* ejb.dependsUpon(util);
* web.dependsUpon(util);
*
* assertEquals(&quot;Dependency mismatch&quot;, true, constraint
* .followsDirective(analyzedPackages));
* }
* </pre>
*
* </blockquote>
* </p>
*
* @author <b>Mike Clark</b>
* @author Clarkware Consulting, Inc.
*/
public class DependencyPrescription extends DependencyDirective {

/**
* Indicates whether the specified packages match the packages in this
* prescription.
*
* @return <code>true</code> if the packages match this constraint
*/
@Override
public boolean followsDirective(Collection<JavaPackage> packages) {
if (packages.size() == packages.size()) {

for (Iterator<JavaPackage> i = packages.iterator(); i.hasNext();) {
Object next = i.next();
JavaPackage nextPackage = (JavaPackage) next;
if (!matchPackage(nextPackage)) {
return false;
}

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<JavaPackage> otherAfferents = b.getAfferents();

if (a.getAfferents().size() == otherAfferents.size()) {
for (Iterator<JavaPackage> 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<JavaPackage> otherEfferents = b.getEfferents();

if (a.getEfferents().size() == otherEfferents.size()) {
for (Iterator<JavaPackage> i = a.getEfferents().iterator(); i.hasNext();) {
JavaPackage efferent = (JavaPackage) i.next();
if (!otherEfferents.contains(efferent)) {
return false;
}
}

return true;
}
}

return false;
}
}
Loading