001: /*
002: * Author: Chris Seguin
003: *
004: * This software has been developed under the copyleft
005: * rules of the GNU General Public License. Please
006: * consult the GNU General Public License for more
007: * details about use and distribution of this software.
008: */
009: package org.acm.seguin.refactor.type;
010:
011: import java.util.Iterator;
012: import java.util.LinkedList;
013: import org.acm.seguin.summary.MethodSummary;
014: import org.acm.seguin.summary.TypeDeclSummary;
015: import org.acm.seguin.summary.TypeSummary;
016: import org.acm.seguin.summary.query.GetTypeSummary;
017:
018: /**
019: * This class searches the type heirarchy looking for abstract methods that
020: * have not yet been instantiated. Abstract methods are gathered into a
021: * linked list. <P>
022: *
023: * This object is used by CreateClass to build a list of abstract methods
024: * that the user will have to overload.
025: *
026: *@author Chris Seguin
027: */
028: public class AbstractMethodFinder {
029: private LinkedList list;
030: private TypeSummary leaf;
031:
032: /**
033: * Constructor for the AbstractMethodFinder object
034: *
035: *@param init the type summary
036: */
037: public AbstractMethodFinder(TypeSummary init) {
038: leaf = init;
039: list = new LinkedList();
040: load();
041: }
042:
043: /**
044: * Constructor for the AbstractMethodFinder object used for unit testing
045: *
046: *@param init the type summary
047: *@param testing dummy variable
048: */
049: AbstractMethodFinder(TypeSummary init, boolean testing) {
050: leaf = init;
051: list = new LinkedList();
052: }
053:
054: /**
055: * Gets the List attribute of the AbstractMethodFinder object
056: *
057: *@return The List value
058: */
059: public LinkedList getList() {
060: return list;
061: }
062:
063: /**
064: * Loads the interface methods
065: */
066: void loadInterfaceMethods() {
067: TypeSummary current = leaf;
068: while (current != null) {
069: // Get the interfaces
070: Iterator iter = current.getImplementedInterfaces();
071: if (iter != null) {
072: while (iter.hasNext()) {
073: TypeDeclSummary nextDecl = (TypeDeclSummary) iter
074: .next();
075: TypeSummary nextType = GetTypeSummary
076: .query(nextDecl);
077: loadInterface(nextType);
078: }
079: }
080:
081: current = nextType(current);
082: }
083: }
084:
085: /**
086: * Removes those methods which have been instantiated (and adds abstract
087: * methods). Uses recursive processing to traverse through the parent
088: * classes first.
089: *
090: *@param current The current type summary
091: */
092: void filter(TypeSummary current) {
093: if (current == null) {
094: return;
095: }
096:
097: // Visit parent first
098: TypeSummary next = nextType(current);
099: filter(next);
100:
101: // Consider each method of the current
102: Iterator iter = current.getMethods();
103: if (iter != null) {
104: while (iter.hasNext()) {
105: MethodSummary nextMethod = (MethodSummary) iter.next();
106: if (nextMethod.isAbstract()) {
107: add(nextMethod);
108: } else {
109: removeImplementations(nextMethod);
110: }
111: }
112: }
113: }
114:
115: /**
116: * Loads the interface methods and then filters out those that have been
117: * instatiated
118: */
119: private void load() {
120: loadInterfaceMethods();
121: filter(leaf);
122: }
123:
124: /**
125: * Loads a particular interface type summary
126: *
127: *@param type the interface
128: */
129: private void loadInterface(TypeSummary type) {
130: if (type == null) {
131: return;
132: }
133:
134: Iterator iter = type.getMethods();
135: if (iter != null) {
136: while (iter.hasNext()) {
137: add((MethodSummary) iter.next());
138: }
139: }
140:
141: iter = type.getImplementedInterfaces();
142: if (iter != null) {
143: while (iter.hasNext()) {
144: TypeDeclSummary nextDecl = (TypeDeclSummary) iter
145: .next();
146: TypeSummary nextType = GetTypeSummary.query(nextDecl);
147: loadInterface(nextType);
148: }
149: }
150: }
151:
152: /**
153: * Gets the next type - finds the parent class type summary
154: *
155: *@param current the current type summary
156: *@return the parent type summary
157: */
158: private TypeSummary nextType(TypeSummary current) {
159: return GetTypeSummary.query(current.getParentClass());
160: }
161:
162: /**
163: * Removes the implementation of a particular method from the linked list
164: *
165: *@param methodSummary the method whose signature we can remove
166: */
167: private void removeImplementations(MethodSummary methodSummary) {
168: Iterator iter = list.iterator();
169: while (iter.hasNext()) {
170: MethodSummary next = (MethodSummary) iter.next();
171: if (methodSummary.checkSignature(next)) {
172: iter.remove();
173: }
174: }
175: }
176:
177: /**
178: * Adds a method summary
179: *
180: *@param methodSummary the method whose signature we want to add
181: */
182: private void add(MethodSummary methodSummary) {
183: Iterator iter = list.iterator();
184: while (iter.hasNext()) {
185: MethodSummary next = (MethodSummary) iter.next();
186: if (methodSummary.checkSignature(next)) {
187: return;
188: }
189: }
190:
191: list.add(methodSummary);
192: }
193: }
|