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.method;
010:
011: import java.util.Iterator;
012: import java.util.LinkedList;
013: import net.sourceforge.jrefactory.ast.ASTMethodDeclaration;
014: import net.sourceforge.jrefactory.ast.SimpleNode;
015: import org.acm.seguin.refactor.ComplexTransform;
016: import org.acm.seguin.refactor.RefactoringException;
017: import org.acm.seguin.summary.TypeDeclSummary;
018: import org.acm.seguin.summary.TypeSummary;
019: import org.acm.seguin.summary.query.GetTypeSummary;
020:
021: /**
022: * Performs the push down method refactoring
023: *
024: *@author Chris Seguin
025: */
026: public class PushDownMethodRefactoring extends
027: InheretenceMethodRefactoring {
028: private LinkedList destinations;
029: private TypeSummary typeSummary;
030:
031: /**
032: * Constructor for the PushDownMethodRefactoring object
033: */
034: protected PushDownMethodRefactoring() {
035: destinations = new LinkedList();
036: }
037:
038: /**
039: * Gets the description of the refactoring
040: *
041: *@return the description
042: */
043: public String getDescription() {
044: return "Moves a method " + methodSummary.getName()
045: + " down into the child classes of "
046: + typeSummary.getName();
047: }
048:
049: /**
050: * Gets the ID attribute of the PushDownMethodRefactoring object
051: *
052: *@return The ID value
053: */
054: public int getID() {
055: return PUSH_DOWN_METHOD;
056: }
057:
058: /**
059: * Adds a feature to the Child attribute of the PushDownMethodRefactoring
060: * object
061: *
062: *@param type The feature to be added to the Child attribute
063: */
064: public void addChild(TypeSummary type) {
065: destinations.add(type);
066: }
067:
068: /**
069: * This specifies the preconditions for applying the refactoring
070: *
071: *@exception RefactoringException Description of Exception
072: */
073: protected void preconditions() throws RefactoringException {
074: if (methodSummary == null) {
075: throw new RefactoringException("No method specified");
076: }
077:
078: typeSummary = (TypeSummary) methodSummary.getParent();
079:
080: Iterator iter = destinations.iterator();
081: while (iter.hasNext()) {
082: TypeSummary next = (TypeSummary) iter.next();
083: TypeDeclSummary parent = next.getParentClass();
084: TypeSummary parentSummary = GetTypeSummary.query(parent);
085:
086: if (parentSummary != typeSummary) {
087: throw new RefactoringException(next.getName()
088: + " is not a subclass of "
089: + typeSummary.getName());
090: }
091:
092: checkDestination(next);
093: }
094: }
095:
096: /**
097: * Moves the method to the parent class
098: */
099: protected void transform() {
100: RemoveMethodTransform rft = new RemoveMethodTransform(
101: methodSummary);
102: ComplexTransform transform = getComplexTransform();
103:
104: removeMethod(typeSummary, transform, rft);
105:
106: // Update the method declaration to have the proper permissions
107: SimpleNode methodDecl = rft.getMethodDeclaration();
108: if (methodDecl == null) {
109: return;
110: }
111:
112: ASTMethodDeclaration decl = updateMethod(methodDecl);
113:
114: Iterator iter = destinations.iterator();
115: while (iter.hasNext()) {
116: TypeSummary next = (TypeSummary) iter.next();
117: addMethodToDest(transform, rft, methodDecl, next);
118: }
119: }
120:
121: /**
122: * Description of the Method
123: *
124: *@param source Description of Parameter
125: *@param transform Description of Parameter
126: *@param rft Description of Parameter
127: */
128: protected void removeMethod(TypeSummary source,
129: ComplexTransform transform, RemoveMethodTransform rft) {
130: transform.add(new AddAbstractMethod(methodSummary));
131: super.removeMethod(source, transform, rft);
132: }
133: }
|