// icycle.beh // // This file contains code which implements the inheritance cycle check. // Visitor which implements the inheritance cycle check. The HashSet // alreadyChecked stores Adjacencies which have already been checked. InhCycleVisitor { {{ public void start() { alreadyChecked = new HashSet(); } public void before(Adjacency a) { // Don't bother checking a if it's already been checked. if (! alreadyChecked.contains(a)) { // Local class Searcher performs the actual check. class Searcher { // inhPath stores all the objects in the hierarchy. HashSet inhPath; // Constructor which initializes inhPath. public Searcher() { inhPath = new HashSet(); } // Recrusive function which visits each object in the // hierarchy. A traversal strategy is not useful here since // we are checking for self-loops. public void search(Adjacency cur) { // Add cur to the alreadyChecked set. alreadyChecked.add(cur); // If cur has not parents, then there can't be an // inheritance cycle here. if (cur.fetchParents() != null) { // Iterate through each of cur's immediate superclasses. // We allow for the possiblity of multiple superclasses // here, even though Java does not support it. Multiple // inheritances is checked for elsewhere. Enumeration e = cur.fetchParents().elements(); while (e.hasMoreElements()) { // The variable p points to a parent. Adjacency p = (Adjacency) e.nextElement(); // If p is already contained in inhPath, then we have // an inheritance cycle. if (inhPath.contains(p)) { System.out.println( "*** Error: " + "Inheritance cycle. Class " + p.fetchIdent() + " is both a subclass and a superclass of class " + cur.fetchIdent() + "." + '\n' ); Main.ecount++; } // Else, add p to inhPath, and recurse. else { inhPath.add(p); search(p); } } } } } // End of local class Searcher. // Create a new Searcher and check a for multiple inheritances. Searcher s = new Searcher(); s.search(a); } } }} }