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.io.File;
012: import java.io.IOException;
013: import org.acm.seguin.refactor.ComplexTransform;
014: import org.acm.seguin.refactor.Refactoring;
015: import org.acm.seguin.refactor.RefactoringException;
016: import org.acm.seguin.summary.FileSummary;
017: import org.acm.seguin.summary.PackageSummary;
018: import org.acm.seguin.summary.Summary;
019: import org.acm.seguin.summary.TypeDeclSummary;
020: import org.acm.seguin.summary.TypeSummary;
021: import org.acm.seguin.summary.query.GetTypeSummary;
022: import org.acm.seguin.summary.query.TopLevelDirectory;
023:
024: /**
025: * Removes a particular class that is an abstract parent.
026: *
027: *@author Chris Seguin
028: */
029: public class RemoveEmptyClassRefactoring extends Refactoring {
030: private TypeSummary typeSummary;
031: private File base;
032:
033: /**
034: * Constructor for the RemoveEmptyClassRefactoring object
035: */
036: protected RemoveEmptyClassRefactoring() {
037: }
038:
039: /**
040: * Sets the ChildClass attribute of the RemoveAbstractParent object
041: *
042: *@param packageName The new Class value
043: *@param className The new Class value
044: */
045: public void setClass(String packageName, String className) {
046: setClass(GetTypeSummary.query(PackageSummary
047: .getPackageSummary(packageName), className));
048: }
049:
050: /**
051: * Sets the ChildClass attribute of the RemoveAbstractParent object
052: *
053: *@param summary The new Class value
054: */
055: public void setClass(TypeSummary summary) {
056: typeSummary = summary;
057: }
058:
059: /**
060: * Gets the description of the refactoring
061: *
062: *@return the description
063: */
064: public String getDescription() {
065: return "Removes the class named " + typeSummary.getName();
066: }
067:
068: /**
069: * Gets the id for this refactoring to track which refactorings are used.
070: *
071: *@return the id
072: */
073: public int getID() {
074: return REMOVE_CLASS;
075: }
076:
077: /**
078: * Gets the FileSummary attribute of the RemoveEmptyClassRefactoring object
079: *
080: *@return The FileSummary value
081: */
082: protected FileSummary getFileSummary() {
083: FileSummary fileSummary = (FileSummary) typeSummary.getParent();
084: return fileSummary;
085: }
086:
087: /**
088: * Checks the preconditions that must be true for this refactoring to be
089: * applied.
090: *
091: *@exception RefactoringException The exception
092: */
093: protected void preconditions() throws RefactoringException {
094: if (typeSummary == null) {
095: throw new RefactoringException("No type specified");
096: }
097:
098: TypeDeclSummary parentDecl = typeSummary.getParentClass();
099: TypeSummary parentSummary;
100: if (parentDecl == null) {
101: parentSummary = GetTypeSummary.query(PackageSummary
102: .getPackageSummary("java.lang"), "Object");
103: } else {
104: parentSummary = GetTypeSummary.query(parentDecl);
105: }
106:
107: if (parentSummary == null) {
108: throw new RefactoringException(
109: "Could not find the parent class for the specified class in the metadata");
110: }
111: FileSummary fileSummary = getFileSummary();
112:
113: if (fileSummary.getFile() == null) {
114: throw new RefactoringException(
115: "This type is contained in a stub. No refactorings allowed.");
116: }
117:
118: if (fileSummary.getTypeCount() != 1) {
119: throw new RefactoringException(
120: "This refactoring works only when the "
121: + "type is alone in a file. Please remove other types from "
122: + fileSummary.getFile().getName());
123: }
124:
125: if ((typeSummary.getFieldCount() > 0)
126: || (typeSummary.getMethodCount() > 0)) {
127: throw new RefactoringException("The "
128: + typeSummary.getName()
129: + " class has at least one method or field");
130: }
131:
132: // Finish the setup
133: File deadFile = fileSummary.getFile();
134: String path = null;
135: try {
136: path = deadFile.getCanonicalPath();
137: } catch (IOException ioe) {
138: path = deadFile.getPath();
139: }
140: File startDir = (new File(path)).getParentFile();
141: String firstFilename = deadFile.getName();
142: base = TopLevelDirectory.query(startDir, firstFilename);
143: }
144:
145: /**
146: * Performs the refactoring by traversing through the files and updating
147: * them.
148: */
149: protected void transform() {
150: ComplexTransform complex = getComplexTransform();
151: FileSummary fileSummary = getFileSummary();
152: complex.removeFile(fileSummary.getFile());
153:
154: String srcPackage = ((PackageSummary) fileSummary.getParent())
155: .getName();
156: String oldClassName = typeSummary.getName();
157: String newClassName;
158:
159: TypeDeclSummary parent = typeSummary.getParentClass();
160: String destPackage;
161: if (parent == null) {
162: newClassName = "Object";
163: destPackage = "java.lang";
164: } else {
165: newClassName = parent.getType();
166: TypeSummary parentTypeSummary = GetTypeSummary
167: .query(parent);
168: Summary one = parentTypeSummary.getParent();
169: while (!(one instanceof PackageSummary)) {
170: one = one.getParent();
171: }
172: destPackage = ((PackageSummary) one).getName();
173: }
174:
175: FileSummary.removeFileSummary(fileSummary.getFile());
176:
177: RemoveClassVisitor rcv = new RemoveClassVisitor(srcPackage,
178: oldClassName, destPackage, newClassName, base, complex);
179: rcv.visit(null);
180: }
181: }
|