package jdepend.framework;
import java.util.*;
/**
* The <code>JavaPackage</code> class represents a Java package.
*
* @author <b>Mike Clark</b>
* @author Clarkware Consulting, Inc.
*/
public class JavaPackage {
private String name;
private int volatility;
private HashSet classes;
private List afferents;
private List efferents;
public JavaPackage(String name) {
this(name, 1);
}
public JavaPackage(String name, int volatility) {
this.name = name;
setVolatility(volatility);
classes = new HashSet();
afferents = new ArrayList();
efferents = new ArrayList();
}
public String getName() {
return name;
}
/**
* @return The package's volatility (0-1).
*/
public int getVolatility() {
return volatility;
}
/**
* @param v Volatility (0-1).
*/
public void setVolatility(int v) {
volatility = v;
}
public boolean containsCycle() {
return collectCycle(new ArrayList());
}
/**
* Collects the packages participating in the first package dependency cycle
* detected which originates from this package.
*
* @param list Collecting object to be populated with the list of
* JavaPackage instances in a cycle.
* @return <code>true</code> if a cycle exist; <code>false</code>
* otherwise.
*/
public boolean collectCycle(List list) {
if (list.contains(this)) {
list.add(this);
return true;
}
list.add(this);
for (Iterator i = getEfferents().iterator(); i.hasNext();) {
JavaPackage efferent = (JavaPackage)i.next();
if (efferent.collectCycle(list)) {
return true;
}
}
list.remove(this);
return false;
}
/**
* Collects all the packages participating in a package dependency cycle
* which originates from this package.
* <p>
* This is a more exhaustive search than that employed by
* <code>collectCycle</code>.
*
* @param list Collecting object to be populated with the list of
* JavaPackage instances in a cycle.
* @return <code>true</code> if a cycle exist; <code>false</code>
* otherwise.
*/
public boolean collectAllCycles(List list) {
if (list.contains(this)) {
list.add(this);
return true;
}
list.add(this);
boolean containsCycle = false;
for (Iterator i = getEfferents().iterator(); i.hasNext();) {
JavaPackage efferent = (JavaPackage)i.next();
if (efferent.collectAllCycles(list)) {
containsCycle = true;
}
}
if (containsCycle) {
return true;
}
list.remove(this);
return false;
}
public void addClass(JavaClass clazz) {
classes.add(clazz);
}
public Collection getClasses() {
return classes;
}
public int getClassCount() {
return classes.size();
}
public int getAbstractClassCount() {
int count = 0;
for (Iterator i = classes.iterator(); i.hasNext();) {
JavaClass clazz = (JavaClass)i.next();
if (clazz.isAbstract()) {
count++;
}
}
return count;
}
public int getConcreteClassCount() {
int count = 0;
for (Iterator i = classes.iterator(); i.hasNext();) {
JavaClass clazz = (JavaClass)i.next();
if (!clazz.isAbstract()) {
count++;
}
}
return count;
}
/**
* Adds the specified Java package as an efferent of this package
* and adds this package as an afferent of it.
*
* @param imported Java package.
*/
public void dependsUpon(JavaPackage imported) {
addEfferent(imported);
imported.addAfferent(this);
}
/**
* Adds the specified Java package as an afferent of this package.
*
* @param jPackage Java package.
*/
public void addAfferent(JavaPackage jPackage) {
if (!jPackage.getName().equals(getName())) {
if (!afferents.contains(jPackage)) {
afferents.add(jPackage);
}
}
}
public Collection getAfferents() {
return afferents;
}
public void setAfferents(Collection afferents) {
this.afferents = new ArrayList(afferents);
}
public void addEfferent(JavaPackage jPackage) {
if (!jPackage.getName().equals(getName())) {
if (!efferents.contains(jPackage)) {
efferents.add(jPackage);
}
}
}
public Collection getEfferents() {
return efferents;
}
public void setEfferents(Collection efferents) {
this.efferents = new ArrayList(efferents);
}
/**
* @return The afferent coupling (Ca) of this package.
*/
public int afferentCoupling() {
return afferents.size();
}
/**
* @return The efferent coupling (Ce) of this package.
*/
public int efferentCoupling() {
return efferents.size();
}
/**
* @return Instability (0-1).
*/
public float instability() {
float totalCoupling = (float) efferentCoupling()
+ (float) afferentCoupling();
if (totalCoupling > 0) {
return efferentCoupling()/totalCoupling;
}
return 0;
}
/**
* @return The package's abstractness (0-1).
*/
public float abstractness() {
if (getClassCount() > 0) {
return (float) getAbstractClassCount() / (float) getClassCount();
}
return 0;
}
/**
* @return The package's distance from the main sequence (D).
*/
public float distance() {
float d = Math.abs(abstractness() + instability() - 1);
return d * volatility;
}
public boolean equals(Object other) {
if (other instanceof JavaPackage) {
JavaPackage otherPackage = (JavaPackage) other;
return otherPackage.getName().equals(getName());
}
return false;
}
public int hashCode() {
return getName().hashCode();
}
}