Source Code Cross Referenced for PushDownRefactoringProcessor.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » internal » corext » refactoring » structure » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.internal.corext.refactoring.structure 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2006, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.structure;
0011:
0012:        import java.util.ArrayList;
0013:        import java.util.Arrays;
0014:        import java.util.Collection;
0015:        import java.util.HashMap;
0016:        import java.util.HashSet;
0017:        import java.util.Iterator;
0018:        import java.util.List;
0019:        import java.util.Map;
0020:        import java.util.Set;
0021:
0022:        import org.eclipse.text.edits.MalformedTreeException;
0023:        import org.eclipse.text.edits.TextEdit;
0024:
0025:        import org.eclipse.core.runtime.Assert;
0026:        import org.eclipse.core.runtime.CoreException;
0027:        import org.eclipse.core.runtime.IProgressMonitor;
0028:        import org.eclipse.core.runtime.OperationCanceledException;
0029:        import org.eclipse.core.runtime.SubProgressMonitor;
0030:
0031:        import org.eclipse.jface.text.BadLocationException;
0032:        import org.eclipse.jface.text.Document;
0033:        import org.eclipse.jface.text.IDocument;
0034:
0035:        import org.eclipse.ltk.core.refactoring.Change;
0036:        import org.eclipse.ltk.core.refactoring.GroupCategory;
0037:        import org.eclipse.ltk.core.refactoring.GroupCategorySet;
0038:        import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
0039:        import org.eclipse.ltk.core.refactoring.RefactoringStatus;
0040:        import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
0041:        import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
0042:
0043:        import org.eclipse.jdt.core.Flags;
0044:        import org.eclipse.jdt.core.ICompilationUnit;
0045:        import org.eclipse.jdt.core.IField;
0046:        import org.eclipse.jdt.core.IJavaElement;
0047:        import org.eclipse.jdt.core.IJavaProject;
0048:        import org.eclipse.jdt.core.IMember;
0049:        import org.eclipse.jdt.core.IMethod;
0050:        import org.eclipse.jdt.core.IType;
0051:        import org.eclipse.jdt.core.ITypeHierarchy;
0052:        import org.eclipse.jdt.core.JavaModelException;
0053:        import org.eclipse.jdt.core.dom.AST;
0054:        import org.eclipse.jdt.core.dom.ASTNode;
0055:        import org.eclipse.jdt.core.dom.ASTRequestor;
0056:        import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
0057:        import org.eclipse.jdt.core.dom.Block;
0058:        import org.eclipse.jdt.core.dom.CompilationUnit;
0059:        import org.eclipse.jdt.core.dom.Expression;
0060:        import org.eclipse.jdt.core.dom.FieldDeclaration;
0061:        import org.eclipse.jdt.core.dom.MarkerAnnotation;
0062:        import org.eclipse.jdt.core.dom.MethodDeclaration;
0063:        import org.eclipse.jdt.core.dom.Modifier;
0064:        import org.eclipse.jdt.core.dom.Type;
0065:        import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
0066:        import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
0067:        import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
0068:        import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
0069:        import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0070:        import org.eclipse.jdt.core.refactoring.descriptors.PushDownDescriptor;
0071:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0072:        import org.eclipse.jdt.core.search.SearchEngine;
0073:        import org.eclipse.jdt.core.search.SearchMatch;
0074:        import org.eclipse.jdt.core.search.SearchPattern;
0075:
0076:        import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
0077:        import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
0078:        import org.eclipse.jdt.internal.corext.dom.ASTNodes;
0079:        import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
0080:        import org.eclipse.jdt.internal.corext.refactoring.Checks;
0081:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
0082:        import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
0083:        import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
0084:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
0085:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
0086:        import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2;
0087:        import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
0088:        import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
0089:        import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
0090:        import org.eclipse.jdt.internal.corext.refactoring.code.ScriptableRefactoring;
0091:        import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
0092:        import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
0093:        import org.eclipse.jdt.internal.corext.refactoring.util.TextEditBasedChangeManager;
0094:        import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
0095:        import org.eclipse.jdt.internal.corext.util.JdtFlags;
0096:        import org.eclipse.jdt.internal.corext.util.Messages;
0097:        import org.eclipse.jdt.internal.corext.util.SearchUtils;
0098:        import org.eclipse.jdt.internal.corext.util.Strings;
0099:
0100:        import org.eclipse.jdt.ui.JavaElementLabels;
0101:
0102:        import org.eclipse.jdt.internal.ui.JavaPlugin;
0103:        import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
0104:
0105:        /**
0106:         * Refactoring processor for the push down refactoring.
0107:         * 
0108:         * @since 3.2
0109:         */
0110:        public final class PushDownRefactoringProcessor extends
0111:                HierarchyProcessor {
0112:
0113:            public static class MemberActionInfo implements  IMemberActionInfo {
0114:
0115:                public static final int NO_ACTION = 2;
0116:
0117:                public static final int PUSH_ABSTRACT_ACTION = 1;
0118:
0119:                public static final int PUSH_DOWN_ACTION = 0;
0120:
0121:                private static void assertValidAction(IMember member, int action) {
0122:                    if (member instanceof  IMethod)
0123:                        Assert.isTrue(action == PUSH_ABSTRACT_ACTION
0124:                                || action == NO_ACTION
0125:                                || action == PUSH_DOWN_ACTION);
0126:                    else if (member instanceof  IField)
0127:                        Assert.isTrue(action == NO_ACTION
0128:                                || action == PUSH_DOWN_ACTION);
0129:                }
0130:
0131:                public static MemberActionInfo create(IMember member, int action) {
0132:                    return new MemberActionInfo(member, action);
0133:                }
0134:
0135:                static IMember[] getMembers(MemberActionInfo[] infos) {
0136:                    IMember[] result = new IMember[infos.length];
0137:                    for (int i = 0; i < result.length; i++) {
0138:                        result[i] = infos[i].getMember();
0139:                    }
0140:                    return result;
0141:                }
0142:
0143:                private int fAction;
0144:
0145:                private final IMember fMember;
0146:
0147:                private MemberActionInfo(IMember member, int action) {
0148:                    assertValidAction(member, action);
0149:                    Assert.isTrue(member instanceof  IField
0150:                            || member instanceof  IMethod);
0151:                    fMember = member;
0152:                    fAction = action;
0153:                }
0154:
0155:                boolean copyJavadocToCopiesInSubclasses() {
0156:                    return isToBeDeletedFromDeclaringClass();
0157:                }
0158:
0159:                public int getAction() {
0160:                    return fAction;
0161:                }
0162:
0163:                public int[] getAvailableActions() {
0164:                    if (isFieldInfo())
0165:                        return new int[] { PUSH_DOWN_ACTION, NO_ACTION };
0166:
0167:                    return new int[] { PUSH_DOWN_ACTION, PUSH_ABSTRACT_ACTION,
0168:                            NO_ACTION };
0169:                }
0170:
0171:                public IMember getMember() {
0172:                    return fMember;
0173:                }
0174:
0175:                int getNewModifiersForCopyInSubclass(int oldModifiers)
0176:                        throws JavaModelException {
0177:                    if (isFieldInfo())
0178:                        return oldModifiers;
0179:                    if (isToBeDeletedFromDeclaringClass())
0180:                        return oldModifiers;
0181:                    int modifiers = oldModifiers;
0182:                    if (isNewMethodToBeDeclaredAbstract()) {
0183:                        if (!JdtFlags.isPublic(fMember))
0184:                            modifiers = Modifier.PROTECTED
0185:                                    | JdtFlags.clearAccessModifiers(modifiers);
0186:                    }
0187:                    return modifiers;
0188:                }
0189:
0190:                int getNewModifiersForOriginal(int oldModifiers)
0191:                        throws JavaModelException {
0192:                    if (isFieldInfo())
0193:                        return oldModifiers;
0194:                    if (isToBeDeletedFromDeclaringClass())
0195:                        return oldModifiers;
0196:                    int modifiers = oldModifiers;
0197:                    if (isNewMethodToBeDeclaredAbstract()) {
0198:                        modifiers = JdtFlags.clearFlag(Modifier.FINAL
0199:                                | Modifier.NATIVE, oldModifiers);
0200:                        modifiers |= Modifier.ABSTRACT;
0201:
0202:                        if (!JdtFlags.isPublic(fMember))
0203:                            modifiers = Modifier.PROTECTED
0204:                                    | JdtFlags.clearAccessModifiers(modifiers);
0205:                    }
0206:                    return modifiers;
0207:                }
0208:
0209:                public boolean isActive() {
0210:                    return getAction() != NO_ACTION;
0211:                }
0212:
0213:                public boolean isEditable() {
0214:                    if (isFieldInfo())
0215:                        return false;
0216:                    if (getAction() == MemberActionInfo.NO_ACTION)
0217:                        return false;
0218:                    return true;
0219:                }
0220:
0221:                boolean isFieldInfo() {
0222:                    return fMember instanceof  IField;
0223:                }
0224:
0225:                boolean isNewMethodToBeDeclaredAbstract()
0226:                        throws JavaModelException {
0227:                    return !isFieldInfo() && !JdtFlags.isAbstract(fMember)
0228:                            && fAction == PUSH_ABSTRACT_ACTION;
0229:                }
0230:
0231:                boolean isToBeCreatedInSubclassesOfDeclaringClass() {
0232:                    return fAction != NO_ACTION;
0233:                }
0234:
0235:                boolean isToBeDeletedFromDeclaringClass() {
0236:                    return isToBePushedDown();
0237:                }
0238:
0239:                public boolean isToBePushedDown() {
0240:                    return fAction == PUSH_DOWN_ACTION;
0241:                }
0242:
0243:                public void setAction(int action) {
0244:                    assertValidAction(fMember, action);
0245:                    if (isFieldInfo())
0246:                        Assert.isTrue(action != PUSH_ABSTRACT_ACTION);
0247:                    fAction = action;
0248:                }
0249:
0250:            }
0251:
0252:            private static final String ATTRIBUTE_ABSTRACT = "abstract"; //$NON-NLS-1$
0253:
0254:            private static final String ATTRIBUTE_PUSH = "push"; //$NON-NLS-1$
0255:
0256:            /** The identifier of this processor */
0257:            public static final String IDENTIFIER = "org.eclipse.jdt.ui.pushDownProcessor"; //$NON-NLS-1$
0258:
0259:            /** The push down group category set */
0260:            private static final GroupCategorySet SET_PUSH_DOWN = new GroupCategorySet(
0261:                    new GroupCategory(
0262:                            "org.eclipse.jdt.internal.corext.pushDown", //$NON-NLS-1$
0263:                            RefactoringCoreMessages.PushDownRefactoring_category_name,
0264:                            RefactoringCoreMessages.PushDownRefactoring_category_description));
0265:
0266:            private static MemberActionInfo[] createInfosForAllPushableFieldsAndMethods(
0267:                    IType type) throws JavaModelException {
0268:                List result = new ArrayList();
0269:                IMember[] pushableMembers = RefactoringAvailabilityTester
0270:                        .getPushDownMembers(type);
0271:                for (int i = 0; i < pushableMembers.length; i++) {
0272:                    result.add(MemberActionInfo.create(pushableMembers[i],
0273:                            MemberActionInfo.NO_ACTION));
0274:                }
0275:                return (MemberActionInfo[]) result
0276:                        .toArray(new MemberActionInfo[result.size()]);
0277:            }
0278:
0279:            private static IMember[] getAbstractMembers(IMember[] members)
0280:                    throws JavaModelException {
0281:                List result = new ArrayList(members.length);
0282:                for (int i = 0; i < members.length; i++) {
0283:                    IMember member = members[i];
0284:                    if (JdtFlags.isAbstract(member))
0285:                        result.add(member);
0286:                }
0287:                return (IMember[]) result.toArray(new IMember[result.size()]);
0288:            }
0289:
0290:            private static CompilationUnitRewrite getCompilationUnitRewrite(
0291:                    final Map rewrites, final ICompilationUnit unit) {
0292:                Assert.isNotNull(rewrites);
0293:                Assert.isNotNull(unit);
0294:                CompilationUnitRewrite rewrite = (CompilationUnitRewrite) rewrites
0295:                        .get(unit);
0296:                if (rewrite == null) {
0297:                    rewrite = new CompilationUnitRewrite(unit);
0298:                    rewrites.put(unit, rewrite);
0299:                }
0300:                return rewrite;
0301:            }
0302:
0303:            private static IJavaElement[] getReferencingElementsFromSameClass(
0304:                    IMember member, IProgressMonitor pm,
0305:                    RefactoringStatus status) throws JavaModelException {
0306:                Assert.isNotNull(member);
0307:                final RefactoringSearchEngine2 engine = new RefactoringSearchEngine2(
0308:                        SearchPattern.createPattern(member,
0309:                                IJavaSearchConstants.REFERENCES,
0310:                                SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE));
0311:                engine.setFiltering(true, true);
0312:                engine.setScope(SearchEngine
0313:                        .createJavaSearchScope(new IJavaElement[] { member
0314:                                .getDeclaringType() }));
0315:                engine.setStatus(status);
0316:                engine.searchPattern(new SubProgressMonitor(pm, 1));
0317:                SearchResultGroup[] groups = (SearchResultGroup[]) engine
0318:                        .getResults();
0319:                Set result = new HashSet(3);
0320:                for (int i = 0; i < groups.length; i++) {
0321:                    SearchResultGroup group = groups[i];
0322:                    SearchMatch[] results = group.getSearchResults();
0323:                    for (int j = 0; j < results.length; j++) {
0324:                        SearchMatch searchResult = results[i];
0325:                        result.add(SearchUtils
0326:                                .getEnclosingJavaElement(searchResult));
0327:                    }
0328:                }
0329:                return (IJavaElement[]) result.toArray(new IJavaElement[result
0330:                        .size()]);
0331:            }
0332:
0333:            private ITypeHierarchy fCachedClassHierarchy;
0334:
0335:            private MemberActionInfo[] fMemberInfos;
0336:
0337:            /**
0338:             * Creates a new push down refactoring processor.
0339:             * 
0340:             * @param members
0341:             *            the members to pull up, or <code>null</code> if invoked by
0342:             *            scripting
0343:             */
0344:            public PushDownRefactoringProcessor(IMember[] members) {
0345:                super (members, null, false);
0346:                if (members != null) {
0347:                    final IType type = RefactoringAvailabilityTester
0348:                            .getTopLevelType(members);
0349:                    try {
0350:                        if (type != null
0351:                                && RefactoringAvailabilityTester
0352:                                        .getPushDownMembers(type).length != 0) {
0353:                            fMembersToMove = new IMember[0];
0354:                            fCachedDeclaringType = type;
0355:                        }
0356:                    } catch (JavaModelException exception) {
0357:                        JavaPlugin.log(exception);
0358:                    }
0359:                }
0360:            }
0361:
0362:            private void addAllRequiredPushableMembers(List queue,
0363:                    IMember member, IProgressMonitor monitor)
0364:                    throws JavaModelException {
0365:                monitor
0366:                        .beginTask(
0367:                                RefactoringCoreMessages.PushDownRefactoring_calculating_required,
0368:                                2);
0369:                IProgressMonitor sub = new SubProgressMonitor(monitor, 1);
0370:                sub
0371:                        .beginTask(
0372:                                RefactoringCoreMessages.PushDownRefactoring_calculating_required,
0373:                                2);
0374:                IMethod[] requiredMethods = ReferenceFinderUtil
0375:                        .getMethodsReferencedIn(new IJavaElement[] { member },
0376:                                new SubProgressMonitor(sub, 1));
0377:                sub = new SubProgressMonitor(sub, 1);
0378:                sub
0379:                        .beginTask(
0380:                                RefactoringCoreMessages.PushDownRefactoring_calculating_required,
0381:                                requiredMethods.length);
0382:                for (int index = 0; index < requiredMethods.length; index++) {
0383:                    IMethod method = requiredMethods[index];
0384:                    if (!MethodChecks.isVirtual(method)
0385:                            && (method.getDeclaringType().equals(
0386:                                    getDeclaringType())
0387:                                    && !queue.contains(method) && RefactoringAvailabilityTester
0388:                                    .isPushDownAvailable(method)))
0389:                        queue.add(method);
0390:                }
0391:                sub.done();
0392:                IField[] requiredFields = ReferenceFinderUtil
0393:                        .getFieldsReferencedIn(new IJavaElement[] { member },
0394:                                new SubProgressMonitor(monitor, 1));
0395:                for (int index = 0; index < requiredFields.length; index++) {
0396:                    IField field = requiredFields[index];
0397:                    if (field.getDeclaringType().equals(getDeclaringType())
0398:                            && !queue.contains(field)
0399:                            && RefactoringAvailabilityTester
0400:                                    .isPushDownAvailable(field))
0401:                        queue.add(field);
0402:                }
0403:                monitor.done();
0404:            }
0405:
0406:            private RefactoringStatus checkAbstractMembersInDestinationClasses(
0407:                    IMember[] membersToPushDown,
0408:                    IType[] destinationClassesForAbstract)
0409:                    throws JavaModelException {
0410:                RefactoringStatus result = new RefactoringStatus();
0411:                IMember[] abstractMembersToPushDown = getAbstractMembers(membersToPushDown);
0412:                for (int index = 0; index < destinationClassesForAbstract.length; index++) {
0413:                    result.merge(MemberCheckUtil.checkMembersInDestinationType(
0414:                            abstractMembersToPushDown,
0415:                            destinationClassesForAbstract[index]));
0416:                }
0417:                return result;
0418:            }
0419:
0420:            private RefactoringStatus checkAccessedFields(IType[] subclasses,
0421:                    IProgressMonitor pm) throws JavaModelException {
0422:                RefactoringStatus result = new RefactoringStatus();
0423:                IMember[] membersToPushDown = MemberActionInfo
0424:                        .getMembers(getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass());
0425:                List pushedDownList = Arrays.asList(membersToPushDown);
0426:                IField[] accessedFields = ReferenceFinderUtil
0427:                        .getFieldsReferencedIn(membersToPushDown, pm);
0428:                for (int i = 0; i < subclasses.length; i++) {
0429:                    IType targetClass = subclasses[i];
0430:                    ITypeHierarchy targetSupertypes = targetClass
0431:                            .newSupertypeHierarchy(null);
0432:                    for (int j = 0; j < accessedFields.length; j++) {
0433:                        IField field = accessedFields[j];
0434:                        boolean isAccessible = pushedDownList.contains(field)
0435:                                || canBeAccessedFrom(field, targetClass,
0436:                                        targetSupertypes)
0437:                                || Flags.isEnum(field.getFlags());
0438:                        if (!isAccessible) {
0439:                            String message = Messages
0440:                                    .format(
0441:                                            RefactoringCoreMessages.PushDownRefactoring_field_not_accessible,
0442:                                            new String[] {
0443:                                                    JavaElementLabels
0444:                                                            .getTextLabel(
0445:                                                                    field,
0446:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED),
0447:                                                    JavaElementLabels
0448:                                                            .getTextLabel(
0449:                                                                    targetClass,
0450:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED) });
0451:                            result.addError(message, JavaStatusContext
0452:                                    .create(field));
0453:                        }
0454:                    }
0455:                }
0456:                pm.done();
0457:                return result;
0458:            }
0459:
0460:            private RefactoringStatus checkAccessedMethods(IType[] subclasses,
0461:                    IProgressMonitor pm) throws JavaModelException {
0462:                RefactoringStatus result = new RefactoringStatus();
0463:                IMember[] membersToPushDown = MemberActionInfo
0464:                        .getMembers(getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass());
0465:                List pushedDownList = Arrays.asList(membersToPushDown);
0466:                IMethod[] accessedMethods = ReferenceFinderUtil
0467:                        .getMethodsReferencedIn(membersToPushDown, pm);
0468:                for (int index = 0; index < subclasses.length; index++) {
0469:                    IType targetClass = subclasses[index];
0470:                    ITypeHierarchy targetSupertypes = targetClass
0471:                            .newSupertypeHierarchy(null);
0472:                    for (int offset = 0; offset < accessedMethods.length; offset++) {
0473:                        IMethod method = accessedMethods[offset];
0474:                        boolean isAccessible = pushedDownList.contains(method)
0475:                                || canBeAccessedFrom(method, targetClass,
0476:                                        targetSupertypes);
0477:                        if (!isAccessible) {
0478:                            String message = Messages
0479:                                    .format(
0480:                                            RefactoringCoreMessages.PushDownRefactoring_method_not_accessible,
0481:                                            new String[] {
0482:                                                    JavaElementLabels
0483:                                                            .getTextLabel(
0484:                                                                    method,
0485:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED),
0486:                                                    JavaElementLabels
0487:                                                            .getTextLabel(
0488:                                                                    targetClass,
0489:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED) });
0490:                            result.addError(message, JavaStatusContext
0491:                                    .create(method));
0492:                        }
0493:                    }
0494:                }
0495:                pm.done();
0496:                return result;
0497:            }
0498:
0499:            private RefactoringStatus checkAccessedTypes(IType[] subclasses,
0500:                    IProgressMonitor pm) throws JavaModelException {
0501:                RefactoringStatus result = new RefactoringStatus();
0502:                IType[] accessedTypes = getTypesReferencedInMovedMembers(pm);
0503:                for (int index = 0; index < subclasses.length; index++) {
0504:                    IType targetClass = subclasses[index];
0505:                    ITypeHierarchy targetSupertypes = targetClass
0506:                            .newSupertypeHierarchy(null);
0507:                    for (int offset = 0; offset < accessedTypes.length; offset++) {
0508:                        IType type = accessedTypes[offset];
0509:                        if (!canBeAccessedFrom(type, targetClass,
0510:                                targetSupertypes)) {
0511:                            String message = Messages
0512:                                    .format(
0513:                                            RefactoringCoreMessages.PushDownRefactoring_type_not_accessible,
0514:                                            new String[] {
0515:                                                    JavaElementLabels
0516:                                                            .getTextLabel(
0517:                                                                    type,
0518:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED),
0519:                                                    JavaElementLabels
0520:                                                            .getTextLabel(
0521:                                                                    targetClass,
0522:                                                                    JavaElementLabels.ALL_FULLY_QUALIFIED) });
0523:                            result.addError(message, JavaStatusContext
0524:                                    .create(type));
0525:                        }
0526:                    }
0527:                }
0528:                pm.done();
0529:                return result;
0530:            }
0531:
0532:            private RefactoringStatus checkElementsAccessedByModifiedMembers(
0533:                    IProgressMonitor pm) throws JavaModelException {
0534:                RefactoringStatus result = new RefactoringStatus();
0535:                pm
0536:                        .beginTask(
0537:                                RefactoringCoreMessages.PushDownRefactoring_check_references,
0538:                                3);
0539:                IType[] subclasses = getAbstractDestinations(new SubProgressMonitor(
0540:                        pm, 1));
0541:                result.merge(checkAccessedTypes(subclasses,
0542:                        new SubProgressMonitor(pm, 1)));
0543:                result.merge(checkAccessedFields(subclasses,
0544:                        new SubProgressMonitor(pm, 1)));
0545:                result.merge(checkAccessedMethods(subclasses,
0546:                        new SubProgressMonitor(pm, 1)));
0547:                pm.done();
0548:                return result;
0549:            }
0550:
0551:            /**
0552:             * {@inheritDoc}
0553:             */
0554:            public RefactoringStatus checkFinalConditions(
0555:                    IProgressMonitor monitor, CheckConditionsContext context)
0556:                    throws CoreException, OperationCanceledException {
0557:                try {
0558:                    monitor
0559:                            .beginTask(
0560:                                    RefactoringCoreMessages.PushDownRefactoring_checking,
0561:                                    5);
0562:                    clearCaches();
0563:                    ICompilationUnit unit = getDeclaringType()
0564:                            .getCompilationUnit();
0565:                    if (fLayer)
0566:                        unit = unit.findWorkingCopy(fOwner);
0567:                    resetWorkingCopies(unit);
0568:                    final RefactoringStatus result = new RefactoringStatus();
0569:                    result
0570:                            .merge(checkMembersInDestinationClasses(new SubProgressMonitor(
0571:                                    monitor, 1)));
0572:                    result
0573:                            .merge(checkElementsAccessedByModifiedMembers(new SubProgressMonitor(
0574:                                    monitor, 1)));
0575:                    result
0576:                            .merge(checkReferencesToPushedDownMembers(new SubProgressMonitor(
0577:                                    monitor, 1)));
0578:                    if (!JdtFlags.isAbstract(getDeclaringType())
0579:                            && getAbstractDeclarationInfos().length != 0)
0580:                        result.merge(checkConstructorCalls(getDeclaringType(),
0581:                                new SubProgressMonitor(monitor, 1)));
0582:                    else
0583:                        monitor.worked(1);
0584:                    if (result.hasFatalError())
0585:                        return result;
0586:                    List members = new ArrayList(fMemberInfos.length);
0587:                    for (int index = 0; index < fMemberInfos.length; index++) {
0588:                        if (fMemberInfos[index].getAction() != MemberActionInfo.NO_ACTION)
0589:                            members.add(fMemberInfos[index].getMember());
0590:                    }
0591:                    fMembersToMove = (IMember[]) members
0592:                            .toArray(new IMember[members.size()]);
0593:                    fChangeManager = createChangeManager(
0594:                            new SubProgressMonitor(monitor, 1), result);
0595:                    if (result.hasFatalError())
0596:                        return result;
0597:                    result.merge(Checks.validateModifiesFiles(ResourceUtil
0598:                            .getFiles(fChangeManager.getAllCompilationUnits()),
0599:                            getRefactoring().getValidationContext()));
0600:                    return result;
0601:                } finally {
0602:                    monitor.done();
0603:                }
0604:            }
0605:
0606:            /**
0607:             * {@inheritDoc}
0608:             */
0609:            public RefactoringStatus checkInitialConditions(
0610:                    IProgressMonitor monitor) throws CoreException,
0611:                    OperationCanceledException {
0612:                try {
0613:                    monitor
0614:                            .beginTask(
0615:                                    RefactoringCoreMessages.PushDownRefactoring_checking,
0616:                                    1);
0617:                    RefactoringStatus status = new RefactoringStatus();
0618:                    status
0619:                            .merge(checkPossibleSubclasses(new SubProgressMonitor(
0620:                                    monitor, 1)));
0621:                    if (status.hasFatalError())
0622:                        return status;
0623:                    status.merge(checkDeclaringType(new SubProgressMonitor(
0624:                            monitor, 1)));
0625:                    if (status.hasFatalError())
0626:                        return status;
0627:                    status.merge(checkIfMembersExist());
0628:                    if (status.hasFatalError())
0629:                        return status;
0630:                    fMemberInfos = createInfosForAllPushableFieldsAndMethods(getDeclaringType());
0631:                    List list = Arrays.asList(fMembersToMove);
0632:                    for (int offset = 0; offset < fMemberInfos.length; offset++) {
0633:                        MemberActionInfo info = fMemberInfos[offset];
0634:                        if (list.contains(info.getMember()))
0635:                            info.setAction(MemberActionInfo.PUSH_DOWN_ACTION);
0636:                    }
0637:                    return status;
0638:                } finally {
0639:                    monitor.done();
0640:                }
0641:            }
0642:
0643:            private RefactoringStatus checkMembersInDestinationClasses(
0644:                    IProgressMonitor monitor) throws JavaModelException {
0645:                monitor
0646:                        .beginTask(
0647:                                RefactoringCoreMessages.PushDownRefactoring_checking,
0648:                                2);
0649:                RefactoringStatus result = new RefactoringStatus();
0650:                IMember[] membersToPushDown = MemberActionInfo
0651:                        .getMembers(getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass());
0652:
0653:                IType[] destinationClassesForNonAbstract = getAbstractDestinations(new SubProgressMonitor(
0654:                        monitor, 1));
0655:                result.merge(checkNonAbstractMembersInDestinationClasses(
0656:                        membersToPushDown, destinationClassesForNonAbstract));
0657:                List list = Arrays
0658:                        .asList(getAbstractMembers(getAbstractDestinations(new SubProgressMonitor(
0659:                                monitor, 1))));
0660:
0661:                IType[] destinationClassesForAbstract = (IType[]) list
0662:                        .toArray(new IType[list.size()]);
0663:                result.merge(checkAbstractMembersInDestinationClasses(
0664:                        membersToPushDown, destinationClassesForAbstract));
0665:                monitor.done();
0666:                return result;
0667:            }
0668:
0669:            private RefactoringStatus checkNonAbstractMembersInDestinationClasses(
0670:                    IMember[] membersToPushDown,
0671:                    IType[] destinationClassesForNonAbstract)
0672:                    throws JavaModelException {
0673:                RefactoringStatus result = new RefactoringStatus();
0674:                List list = new ArrayList(); // Arrays.asList does not support removing
0675:                list.addAll(Arrays.asList(membersToPushDown));
0676:                list.removeAll(Arrays
0677:                        .asList(getAbstractMembers(membersToPushDown)));
0678:                IMember[] nonAbstractMembersToPushDown = (IMember[]) list
0679:                        .toArray(new IMember[list.size()]);
0680:                for (int i = 0; i < destinationClassesForNonAbstract.length; i++) {
0681:                    result.merge(MemberCheckUtil.checkMembersInDestinationType(
0682:                            nonAbstractMembersToPushDown,
0683:                            destinationClassesForNonAbstract[i]));
0684:                }
0685:                return result;
0686:            }
0687:
0688:            private RefactoringStatus checkPossibleSubclasses(
0689:                    IProgressMonitor pm) throws JavaModelException {
0690:                IType[] modifiableSubclasses = getAbstractDestinations(pm);
0691:                if (modifiableSubclasses.length == 0) {
0692:                    String msg = Messages
0693:                            .format(
0694:                                    RefactoringCoreMessages.PushDownRefactoring_no_subclasses,
0695:                                    new String[] { JavaElementLabels
0696:                                            .getTextLabel(
0697:                                                    getDeclaringType(),
0698:                                                    JavaElementLabels.ALL_FULLY_QUALIFIED) });
0699:                    return RefactoringStatus.createFatalErrorStatus(msg);
0700:                }
0701:                return new RefactoringStatus();
0702:            }
0703:
0704:            private RefactoringStatus checkReferencesToPushedDownMembers(
0705:                    IProgressMonitor monitor) throws JavaModelException {
0706:                List fields = new ArrayList(fMemberInfos.length);
0707:                for (int index = 0; index < fMemberInfos.length; index++) {
0708:                    MemberActionInfo info = fMemberInfos[index];
0709:                    if (info.isToBePushedDown())
0710:                        fields.add(info.getMember());
0711:                }
0712:                IMember[] membersToPush = (IMember[]) fields
0713:                        .toArray(new IMember[fields.size()]);
0714:                RefactoringStatus result = new RefactoringStatus();
0715:                List movedMembers = Arrays
0716:                        .asList(MemberActionInfo
0717:                                .getMembers(getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass()));
0718:                monitor
0719:                        .beginTask(
0720:                                RefactoringCoreMessages.PushDownRefactoring_check_references,
0721:                                membersToPush.length);
0722:                for (int index = 0; index < membersToPush.length; index++) {
0723:                    IMember member = membersToPush[index];
0724:                    String label = createLabel(member);
0725:                    IJavaElement[] referencing = getReferencingElementsFromSameClass(
0726:                            member, new SubProgressMonitor(monitor, 1), result);
0727:                    for (int offset = 0; offset < referencing.length; offset++) {
0728:                        IJavaElement element = referencing[offset];
0729:                        if (movedMembers.contains(element))
0730:                            continue;
0731:                        if (!(element instanceof  IMember))
0732:                            continue;
0733:                        IMember referencingMember = (IMember) element;
0734:                        Object[] keys = { label, createLabel(referencingMember) };
0735:                        String msg = Messages
0736:                                .format(
0737:                                        RefactoringCoreMessages.PushDownRefactoring_referenced,
0738:                                        keys);
0739:                        result.addError(msg, JavaStatusContext
0740:                                .create(referencingMember));
0741:                    }
0742:                }
0743:                monitor.done();
0744:                return result;
0745:            }
0746:
0747:            public void computeAdditionalRequiredMembersToPushDown(
0748:                    IProgressMonitor monitor) throws JavaModelException {
0749:                List list = Arrays
0750:                        .asList(getAdditionalRequiredMembers(monitor));
0751:                for (int index = 0; index < fMemberInfos.length; index++) {
0752:                    MemberActionInfo info = fMemberInfos[index];
0753:                    if (list.contains(info.getMember()))
0754:                        info.setAction(MemberActionInfo.PUSH_DOWN_ACTION);
0755:                }
0756:            }
0757:
0758:            private void copyBodyOfPushedDownMethod(ASTRewrite targetRewrite,
0759:                    IMethod method, MethodDeclaration oldMethod,
0760:                    MethodDeclaration newMethod, TypeVariableMaplet[] mapping)
0761:                    throws JavaModelException {
0762:                Block body = oldMethod.getBody();
0763:                if (body == null) {
0764:                    newMethod.setBody(null);
0765:                    return;
0766:                }
0767:                try {
0768:                    final IDocument document = new Document(method
0769:                            .getCompilationUnit().getBuffer().getContents());
0770:                    final ASTRewrite rewriter = ASTRewrite
0771:                            .create(body.getAST());
0772:                    final ITrackedNodePosition position = rewriter.track(body);
0773:                    body.accept(new TypeVariableMapper(rewriter, mapping));
0774:                    rewriter.rewriteAST(
0775:                            document,
0776:                            getDeclaringType().getCompilationUnit()
0777:                                    .getJavaProject().getOptions(true)).apply(
0778:                            document, TextEdit.NONE);
0779:                    String content = document.get(position.getStartPosition(),
0780:                            position.getLength());
0781:                    String[] lines = Strings.convertIntoLines(content);
0782:                    Strings.trimIndentation(lines, method.getJavaProject(),
0783:                            false);
0784:                    content = Strings.concatenate(lines, StubUtility
0785:                            .getLineDelimiterUsed(method));
0786:                    newMethod.setBody((Block) targetRewrite
0787:                            .createStringPlaceholder(content, ASTNode.BLOCK));
0788:                } catch (MalformedTreeException exception) {
0789:                    JavaPlugin.log(exception);
0790:                } catch (BadLocationException exception) {
0791:                    JavaPlugin.log(exception);
0792:                }
0793:            }
0794:
0795:            private void copyMembers(Collection adjustors, Map adjustments,
0796:                    Map rewrites, RefactoringStatus status,
0797:                    MemberActionInfo[] infos, IType[] destinations,
0798:                    CompilationUnitRewrite sourceRewriter,
0799:                    CompilationUnitRewrite unitRewriter,
0800:                    IProgressMonitor monitor) throws JavaModelException {
0801:                try {
0802:                    monitor
0803:                            .beginTask(
0804:                                    RefactoringCoreMessages.PushDownRefactoring_checking,
0805:                                    1);
0806:                    IType type = null;
0807:                    TypeVariableMaplet[] mapping = null;
0808:                    for (int index = 0; index < destinations.length; index++) {
0809:                        type = destinations[index];
0810:                        mapping = TypeVariableUtil.super TypeToInheritedType(
0811:                                getDeclaringType(), type);
0812:                        if (unitRewriter.getCu().equals(
0813:                                type.getCompilationUnit())) {
0814:                            IMember member = null;
0815:                            MemberVisibilityAdjustor adjustor = null;
0816:                            AbstractTypeDeclaration declaration = ASTNodeSearchUtil
0817:                                    .getAbstractTypeDeclarationNode(type,
0818:                                            unitRewriter.getRoot());
0819:                            for (int offset = infos.length - 1; offset >= 0; offset--) {
0820:                                member = infos[offset].getMember();
0821:                                adjustor = new MemberVisibilityAdjustor(type,
0822:                                        member);
0823:                                if (infos[offset]
0824:                                        .isNewMethodToBeDeclaredAbstract())
0825:                                    adjustor.setIncoming(false);
0826:                                adjustor.setRewrite(sourceRewriter
0827:                                        .getASTRewrite(), sourceRewriter
0828:                                        .getRoot());
0829:                                adjustor.setRewrites(rewrites);
0830:
0831:                                // TW: set to error if bug 78387 is fixed
0832:                                adjustor
0833:                                        .setFailureSeverity(RefactoringStatus.WARNING);
0834:
0835:                                adjustor.setStatus(status);
0836:                                adjustor.setAdjustments(adjustments);
0837:                                adjustor
0838:                                        .adjustVisibility(new SubProgressMonitor(
0839:                                                monitor, 1));
0840:                                adjustments.remove(member);
0841:                                adjustors.add(adjustor);
0842:                                status.merge(checkProjectCompliance(
0843:                                        getCompilationUnitRewrite(rewrites,
0844:                                                getDeclaringType()
0845:                                                        .getCompilationUnit()),
0846:                                        type, new IMember[] { infos[offset]
0847:                                                .getMember() }));
0848:                                if (infos[offset].isFieldInfo()) {
0849:                                    final VariableDeclarationFragment oldField = ASTNodeSearchUtil
0850:                                            .getFieldDeclarationFragmentNode(
0851:                                                    (IField) infos[offset]
0852:                                                            .getMember(),
0853:                                                    sourceRewriter.getRoot());
0854:                                    if (oldField != null) {
0855:                                        FieldDeclaration newField = createNewFieldDeclarationNode(
0856:                                                infos[offset], sourceRewriter
0857:                                                        .getRoot(), mapping,
0858:                                                unitRewriter.getASTRewrite(),
0859:                                                oldField);
0860:                                        unitRewriter
0861:                                                .getASTRewrite()
0862:                                                .getListRewrite(
0863:                                                        declaration,
0864:                                                        declaration
0865:                                                                .getBodyDeclarationsProperty())
0866:                                                .insertAt(
0867:                                                        newField,
0868:                                                        ASTNodes
0869:                                                                .getInsertionIndex(
0870:                                                                        newField,
0871:                                                                        declaration
0872:                                                                                .bodyDeclarations()),
0873:                                                        unitRewriter
0874:                                                                .createCategorizedGroupDescription(
0875:                                                                        RefactoringCoreMessages.HierarchyRefactoring_add_member,
0876:                                                                        SET_PUSH_DOWN));
0877:                                        ImportRewriteUtil.addImports(
0878:                                                unitRewriter, oldField
0879:                                                        .getParent(),
0880:                                                new HashMap(), new HashMap(),
0881:                                                false);
0882:                                    }
0883:                                } else {
0884:                                    final MethodDeclaration oldMethod = ASTNodeSearchUtil
0885:                                            .getMethodDeclarationNode(
0886:                                                    (IMethod) infos[offset]
0887:                                                            .getMember(),
0888:                                                    sourceRewriter.getRoot());
0889:                                    if (oldMethod != null) {
0890:                                        MethodDeclaration newMethod = createNewMethodDeclarationNode(
0891:                                                infos[offset], mapping,
0892:                                                unitRewriter, oldMethod);
0893:                                        unitRewriter
0894:                                                .getASTRewrite()
0895:                                                .getListRewrite(
0896:                                                        declaration,
0897:                                                        declaration
0898:                                                                .getBodyDeclarationsProperty())
0899:                                                .insertAt(
0900:                                                        newMethod,
0901:                                                        ASTNodes
0902:                                                                .getInsertionIndex(
0903:                                                                        newMethod,
0904:                                                                        declaration
0905:                                                                                .bodyDeclarations()),
0906:                                                        unitRewriter
0907:                                                                .createCategorizedGroupDescription(
0908:                                                                        RefactoringCoreMessages.HierarchyRefactoring_add_member,
0909:                                                                        SET_PUSH_DOWN));
0910:                                        ImportRewriteUtil.addImports(
0911:                                                unitRewriter, oldMethod,
0912:                                                new HashMap(), new HashMap(),
0913:                                                false);
0914:                                    }
0915:                                }
0916:                            }
0917:                        }
0918:                    }
0919:                } finally {
0920:                    monitor.done();
0921:                }
0922:            }
0923:
0924:            /**
0925:             * {@inheritDoc}
0926:             */
0927:            public Change createChange(IProgressMonitor pm)
0928:                    throws CoreException, OperationCanceledException {
0929:                try {
0930:                    final Map arguments = new HashMap();
0931:                    String project = null;
0932:                    final IType declaring = getDeclaringType();
0933:                    final IJavaProject javaProject = declaring.getJavaProject();
0934:                    if (javaProject != null)
0935:                        project = javaProject.getElementName();
0936:                    int flags = JavaRefactoringDescriptor.JAR_MIGRATION
0937:                            | JavaRefactoringDescriptor.JAR_REFACTORING
0938:                            | RefactoringDescriptor.STRUCTURAL_CHANGE
0939:                            | RefactoringDescriptor.MULTI_CHANGE;
0940:                    try {
0941:                        if (declaring.isLocal() || declaring.isAnonymous())
0942:                            flags |= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
0943:                    } catch (JavaModelException exception) {
0944:                        JavaPlugin.log(exception);
0945:                    }
0946:                    final String description = fMembersToMove.length == 1 ? Messages
0947:                            .format(
0948:                                    RefactoringCoreMessages.PushDownRefactoring_descriptor_description_short_multi,
0949:                                    fMembersToMove[0].getElementName())
0950:                            : RefactoringCoreMessages.PushDownRefactoring_descriptor_description_short;
0951:                    final String header = fMembersToMove.length == 1 ? Messages
0952:                            .format(
0953:                                    RefactoringCoreMessages.PushDownRefactoring_descriptor_description_full,
0954:                                    new String[] {
0955:                                            JavaElementLabels
0956:                                                    .getElementLabel(
0957:                                                            fMembersToMove[0],
0958:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED),
0959:                                            JavaElementLabels
0960:                                                    .getElementLabel(
0961:                                                            declaring,
0962:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED) })
0963:                            : Messages
0964:                                    .format(
0965:                                            RefactoringCoreMessages.PushDownRefactoring_descriptor_description,
0966:                                            new String[] { JavaElementLabels
0967:                                                    .getElementLabel(
0968:                                                            declaring,
0969:                                                            JavaElementLabels.ALL_FULLY_QUALIFIED) });
0970:                    final JDTRefactoringDescriptorComment comment = new JDTRefactoringDescriptorComment(
0971:                            project, this , header);
0972:                    final String[] settings = new String[fMembersToMove.length];
0973:                    for (int index = 0; index < settings.length; index++)
0974:                        settings[index] = JavaElementLabels.getElementLabel(
0975:                                fMembersToMove[index],
0976:                                JavaElementLabels.ALL_FULLY_QUALIFIED);
0977:                    comment
0978:                            .addSetting(JDTRefactoringDescriptorComment
0979:                                    .createCompositeSetting(
0980:                                            RefactoringCoreMessages.PushDownRefactoring_pushed_members_pattern,
0981:                                            settings));
0982:                    addSuperTypeSettings(comment, true);
0983:                    final PushDownDescriptor descriptor = new PushDownDescriptor(
0984:                            project, description, comment.asString(),
0985:                            arguments, flags);
0986:                    if (fCachedDeclaringType != null)
0987:                        arguments.put(
0988:                                JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT,
0989:                                JavaRefactoringDescriptorUtil.elementToHandle(
0990:                                        project, fCachedDeclaringType));
0991:                    for (int index = 0; index < fMembersToMove.length; index++) {
0992:                        arguments.put(
0993:                                JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT
0994:                                        + (index + 1),
0995:                                JavaRefactoringDescriptorUtil.elementToHandle(
0996:                                        project, fMembersToMove[index]));
0997:                        for (int offset = 0; offset < fMemberInfos.length; offset++) {
0998:                            if (fMemberInfos[offset].getMember().equals(
0999:                                    fMembersToMove[index])) {
1000:                                switch (fMemberInfos[offset].getAction()) {
1001:                                case MemberActionInfo.PUSH_ABSTRACT_ACTION:
1002:                                    arguments.put(ATTRIBUTE_ABSTRACT
1003:                                            + (index + 1), Boolean
1004:                                            .valueOf(true).toString());
1005:                                    break;
1006:                                case MemberActionInfo.PUSH_DOWN_ACTION:
1007:                                    arguments.put(ATTRIBUTE_PUSH + (index + 1),
1008:                                            Boolean.valueOf(true).toString());
1009:                                    break;
1010:                                }
1011:                            }
1012:                        }
1013:                    }
1014:                    return new DynamicValidationRefactoringChange(
1015:                            descriptor,
1016:                            RefactoringCoreMessages.PushDownRefactoring_change_name,
1017:                            fChangeManager.getAllChanges());
1018:                } finally {
1019:                    pm.done();
1020:                    clearCaches();
1021:                }
1022:            }
1023:
1024:            private TextEditBasedChangeManager createChangeManager(
1025:                    final IProgressMonitor monitor,
1026:                    final RefactoringStatus status) throws CoreException {
1027:                Assert.isNotNull(monitor);
1028:                Assert.isNotNull(status);
1029:                try {
1030:                    monitor
1031:                            .beginTask(
1032:                                    RefactoringCoreMessages.PushDownRefactoring_checking,
1033:                                    7);
1034:                    final ICompilationUnit source = getDeclaringType()
1035:                            .getCompilationUnit();
1036:                    final CompilationUnitRewrite sourceRewriter = new CompilationUnitRewrite(
1037:                            source);
1038:                    final Map rewrites = new HashMap(2);
1039:                    rewrites.put(source, sourceRewriter);
1040:                    IType[] types = getHierarchyOfDeclaringClass(
1041:                            new SubProgressMonitor(monitor, 1)).getSubclasses(
1042:                            getDeclaringType());
1043:                    final Set result = new HashSet(types.length + 1);
1044:                    for (int index = 0; index < types.length; index++)
1045:                        result.add(types[index].getCompilationUnit());
1046:                    result.add(source);
1047:                    final Map adjustments = new HashMap();
1048:                    final List adjustors = new ArrayList();
1049:                    final ICompilationUnit[] units = (ICompilationUnit[]) result
1050:                            .toArray(new ICompilationUnit[result.size()]);
1051:                    ICompilationUnit unit = null;
1052:                    CompilationUnitRewrite rewrite = null;
1053:                    final IProgressMonitor sub = new SubProgressMonitor(
1054:                            monitor, 4);
1055:                    try {
1056:                        sub
1057:                                .beginTask(
1058:                                        RefactoringCoreMessages.PushDownRefactoring_checking,
1059:                                        units.length * 4);
1060:                        for (int index = 0; index < units.length; index++) {
1061:                            unit = units[index];
1062:                            rewrite = getCompilationUnitRewrite(rewrites, unit);
1063:                            if (unit.equals(sourceRewriter.getCu())) {
1064:                                final AbstractTypeDeclaration declaration = ASTNodeSearchUtil
1065:                                        .getAbstractTypeDeclarationNode(
1066:                                                getDeclaringType(), rewrite
1067:                                                        .getRoot());
1068:                                if (!JdtFlags.isAbstract(getDeclaringType())
1069:                                        && getAbstractDeclarationInfos().length != 0)
1070:                                    ModifierRewrite
1071:                                            .create(rewrite.getASTRewrite(),
1072:                                                    declaration)
1073:                                            .setModifiers(
1074:                                                    (Modifier.ABSTRACT | declaration
1075:                                                            .getModifiers()),
1076:                                                    rewrite
1077:                                                            .createCategorizedGroupDescription(
1078:                                                                    RefactoringCoreMessages.PushDownRefactoring_make_abstract,
1079:                                                                    SET_PUSH_DOWN));
1080:                                deleteDeclarationNodes(sourceRewriter, false,
1081:                                        rewrite, Arrays
1082:                                                .asList(getDeletableMembers()),
1083:                                        SET_PUSH_DOWN);
1084:                                MemberActionInfo[] methods = getAbstractDeclarationInfos();
1085:                                for (int offset = 0; offset < methods.length; offset++)
1086:                                    declareMethodAbstract(methods[offset],
1087:                                            sourceRewriter, rewrite);
1088:                            }
1089:                            final IMember[] members = getAbstractMembers(getAbstractDestinations(new SubProgressMonitor(
1090:                                    monitor, 1)));
1091:                            final IType[] classes = new IType[members.length];
1092:                            for (int offset = 0; offset < members.length; offset++)
1093:                                classes[offset] = (IType) members[offset];
1094:                            copyMembers(adjustors, adjustments, rewrites,
1095:                                    status, getAbstractMemberInfos(), classes,
1096:                                    sourceRewriter, rewrite, sub);
1097:                            copyMembers(
1098:                                    adjustors,
1099:                                    adjustments,
1100:                                    rewrites,
1101:                                    status,
1102:                                    getEffectedMemberInfos(),
1103:                                    getAbstractDestinations(new SubProgressMonitor(
1104:                                            monitor, 1)), sourceRewriter,
1105:                                    rewrite, sub);
1106:                            if (monitor.isCanceled())
1107:                                throw new OperationCanceledException();
1108:                        }
1109:                    } finally {
1110:                        sub.done();
1111:                    }
1112:                    if (!adjustors.isEmpty() && !adjustments.isEmpty()) {
1113:                        final MemberVisibilityAdjustor adjustor = (MemberVisibilityAdjustor) adjustors
1114:                                .get(0);
1115:                        adjustor.rewriteVisibility(new SubProgressMonitor(
1116:                                monitor, 1));
1117:                    }
1118:                    final TextEditBasedChangeManager manager = new TextEditBasedChangeManager();
1119:                    for (final Iterator iterator = rewrites.keySet().iterator(); iterator
1120:                            .hasNext();) {
1121:                        unit = (ICompilationUnit) iterator.next();
1122:                        rewrite = (CompilationUnitRewrite) rewrites.get(unit);
1123:                        if (rewrite != null)
1124:                            manager.manage(unit, rewrite.createChange());
1125:                    }
1126:                    return manager;
1127:                } finally {
1128:                    monitor.done();
1129:                }
1130:            }
1131:
1132:            private FieldDeclaration createNewFieldDeclarationNode(
1133:                    MemberActionInfo info, CompilationUnit declaringCuNode,
1134:                    TypeVariableMaplet[] mapping, ASTRewrite rewrite,
1135:                    VariableDeclarationFragment oldFieldFragment)
1136:                    throws JavaModelException {
1137:                Assert.isTrue(info.isFieldInfo());
1138:                IField field = (IField) info.getMember();
1139:                AST ast = rewrite.getAST();
1140:                VariableDeclarationFragment newFragment = ast
1141:                        .newVariableDeclarationFragment();
1142:                newFragment.setExtraDimensions(oldFieldFragment
1143:                        .getExtraDimensions());
1144:                Expression initializer = oldFieldFragment.getInitializer();
1145:                if (initializer != null) {
1146:                    Expression newInitializer = null;
1147:                    if (mapping.length > 0)
1148:                        newInitializer = createPlaceholderForExpression(
1149:                                initializer, field.getCompilationUnit(),
1150:                                mapping, rewrite);
1151:                    else
1152:                        newInitializer = createPlaceholderForExpression(
1153:                                initializer, field.getCompilationUnit(),
1154:                                rewrite);
1155:                    newFragment.setInitializer(newInitializer);
1156:                }
1157:                newFragment.setName(ast.newSimpleName(oldFieldFragment
1158:                        .getName().getIdentifier()));
1159:                FieldDeclaration newField = ast
1160:                        .newFieldDeclaration(newFragment);
1161:                FieldDeclaration oldField = ASTNodeSearchUtil
1162:                        .getFieldDeclarationNode(field, declaringCuNode);
1163:                if (info.copyJavadocToCopiesInSubclasses())
1164:                    copyJavadocNode(rewrite, oldField, newField);
1165:                copyAnnotations(oldField, newField);
1166:                newField.modifiers().addAll(
1167:                        ASTNodeFactory.newModifiers(ast, info
1168:                                .getNewModifiersForCopyInSubclass(oldField
1169:                                        .getModifiers())));
1170:                Type oldType = oldField.getType();
1171:                ICompilationUnit cu = field.getCompilationUnit();
1172:                Type newType = null;
1173:                if (mapping.length > 0) {
1174:                    newType = createPlaceholderForType(oldType, cu, mapping,
1175:                            rewrite);
1176:                } else
1177:                    newType = createPlaceholderForType(oldType, cu, rewrite);
1178:                newField.setType(newType);
1179:                return newField;
1180:            }
1181:
1182:            private MethodDeclaration createNewMethodDeclarationNode(
1183:                    MemberActionInfo info, TypeVariableMaplet[] mapping,
1184:                    CompilationUnitRewrite rewriter, MethodDeclaration oldMethod)
1185:                    throws JavaModelException {
1186:                Assert.isTrue(!info.isFieldInfo());
1187:                IMethod method = (IMethod) info.getMember();
1188:                ASTRewrite rewrite = rewriter.getASTRewrite();
1189:                AST ast = rewrite.getAST();
1190:                MethodDeclaration newMethod = ast.newMethodDeclaration();
1191:                copyBodyOfPushedDownMethod(rewrite, method, oldMethod,
1192:                        newMethod, mapping);
1193:                newMethod.setConstructor(oldMethod.isConstructor());
1194:                newMethod.setExtraDimensions(oldMethod.getExtraDimensions());
1195:                if (info.copyJavadocToCopiesInSubclasses())
1196:                    copyJavadocNode(rewrite, oldMethod, newMethod);
1197:                final IJavaProject project = rewriter.getCu().getJavaProject();
1198:                if (info.isNewMethodToBeDeclaredAbstract()
1199:                        && JavaModelUtil.is50OrHigher(project)
1200:                        && JavaPreferencesSettings
1201:                                .getCodeGenerationSettings(project).overrideAnnotation) {
1202:                    final MarkerAnnotation annotation = ast
1203:                            .newMarkerAnnotation();
1204:                    annotation.setTypeName(ast.newSimpleName("Override")); //$NON-NLS-1$
1205:                    newMethod.modifiers().add(annotation);
1206:                }
1207:                copyAnnotations(oldMethod, newMethod);
1208:                newMethod.modifiers().addAll(
1209:                        ASTNodeFactory.newModifiers(ast, info
1210:                                .getNewModifiersForCopyInSubclass(oldMethod
1211:                                        .getModifiers())));
1212:                newMethod.setName(ast.newSimpleName(oldMethod.getName()
1213:                        .getIdentifier()));
1214:                copyReturnType(rewrite, method.getCompilationUnit(), oldMethod,
1215:                        newMethod, mapping);
1216:                copyParameters(rewrite, method.getCompilationUnit(), oldMethod,
1217:                        newMethod, mapping);
1218:                copyThrownExceptions(oldMethod, newMethod);
1219:                copyTypeParameters(oldMethod, newMethod);
1220:                return newMethod;
1221:            }
1222:
1223:            private void declareMethodAbstract(MemberActionInfo info,
1224:                    CompilationUnitRewrite sourceRewrite,
1225:                    CompilationUnitRewrite unitRewrite)
1226:                    throws JavaModelException {
1227:                Assert.isTrue(!info.isFieldInfo());
1228:                IMethod method = (IMethod) info.getMember();
1229:                if (JdtFlags.isAbstract(method))
1230:                    return;
1231:                final MethodDeclaration declaration = ASTNodeSearchUtil
1232:                        .getMethodDeclarationNode(method, sourceRewrite
1233:                                .getRoot());
1234:                unitRewrite.getASTRewrite().remove(declaration.getBody(), null);
1235:                sourceRewrite.getImportRemover().registerRemovedNode(
1236:                        declaration.getBody());
1237:                ModifierRewrite
1238:                        .create(unitRewrite.getASTRewrite(), declaration)
1239:                        .setModifiers(
1240:                                info.getNewModifiersForOriginal(declaration
1241:                                        .getModifiers()), null);
1242:            }
1243:
1244:            private MemberActionInfo[] getAbstractDeclarationInfos()
1245:                    throws JavaModelException {
1246:                List result = new ArrayList(fMemberInfos.length);
1247:                for (int index = 0; index < fMemberInfos.length; index++) {
1248:                    MemberActionInfo info = fMemberInfos[index];
1249:                    if (info.isNewMethodToBeDeclaredAbstract())
1250:                        result.add(info);
1251:                }
1252:                return (MemberActionInfo[]) result
1253:                        .toArray(new MemberActionInfo[result.size()]);
1254:            }
1255:
1256:            private IType[] getAbstractDestinations(IProgressMonitor monitor)
1257:                    throws JavaModelException {
1258:                IType[] allDirectSubclasses = getHierarchyOfDeclaringClass(
1259:                        monitor).getSubclasses(getDeclaringType());
1260:                List result = new ArrayList(allDirectSubclasses.length);
1261:                for (int index = 0; index < allDirectSubclasses.length; index++) {
1262:                    IType subclass = allDirectSubclasses[index];
1263:                    if (subclass.exists() && !subclass.isBinary()
1264:                            && !subclass.isReadOnly()
1265:                            && subclass.getCompilationUnit() != null
1266:                            && subclass.isStructureKnown())
1267:                        result.add(subclass);
1268:                }
1269:                return (IType[]) result.toArray(new IType[result.size()]);
1270:            }
1271:
1272:            private MemberActionInfo[] getAbstractMemberInfos()
1273:                    throws JavaModelException {
1274:                List result = new ArrayList(fMemberInfos.length);
1275:                for (int index = 0; index < fMemberInfos.length; index++) {
1276:                    MemberActionInfo info = fMemberInfos[index];
1277:                    if (info.isToBeCreatedInSubclassesOfDeclaringClass()
1278:                            && JdtFlags.isAbstract(info.getMember()))
1279:                        result.add(info);
1280:                }
1281:                return (MemberActionInfo[]) result
1282:                        .toArray(new MemberActionInfo[result.size()]);
1283:            }
1284:
1285:            public IMember[] getAdditionalRequiredMembers(
1286:                    IProgressMonitor monitor) throws JavaModelException {
1287:                IMember[] members = MemberActionInfo
1288:                        .getMembers(getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass());
1289:                monitor
1290:                        .beginTask(
1291:                                RefactoringCoreMessages.PushDownRefactoring_calculating_required,
1292:                                members.length);// not
1293:                // true,
1294:                // but
1295:                // not
1296:                // easy
1297:                // to
1298:                // give
1299:                // anything
1300:                // better
1301:                List queue = new ArrayList(members.length);
1302:                queue.addAll(Arrays.asList(members));
1303:                if (queue.isEmpty())
1304:                    return new IMember[0];
1305:                int i = 0;
1306:                IMember current;
1307:                do {
1308:                    current = (IMember) queue.get(i);
1309:                    addAllRequiredPushableMembers(queue, current,
1310:                            new SubProgressMonitor(monitor, 1));
1311:                    i++;
1312:                    if (queue.size() == i)
1313:                        current = null;
1314:                } while (current != null);
1315:                queue.removeAll(Arrays.asList(members));// report only additional
1316:                return (IMember[]) queue.toArray(new IMember[queue.size()]);
1317:            }
1318:
1319:            private IMember[] getDeletableMembers() {
1320:                List result = new ArrayList(fMemberInfos.length);
1321:                for (int i = 0; i < fMemberInfos.length; i++) {
1322:                    MemberActionInfo info = fMemberInfos[i];
1323:                    if (info.isToBeDeletedFromDeclaringClass())
1324:                        result.add(info.getMember());
1325:                }
1326:                return (IMember[]) result.toArray(new IMember[result.size()]);
1327:            }
1328:
1329:            private MemberActionInfo[] getEffectedMemberInfos()
1330:                    throws JavaModelException {
1331:                List result = new ArrayList(fMemberInfos.length);
1332:                for (int i = 0; i < fMemberInfos.length; i++) {
1333:                    MemberActionInfo info = fMemberInfos[i];
1334:                    if (info.isToBeCreatedInSubclassesOfDeclaringClass()
1335:                            && !JdtFlags.isAbstract(info.getMember()))
1336:                        result.add(info);
1337:                }
1338:                return (MemberActionInfo[]) result
1339:                        .toArray(new MemberActionInfo[result.size()]);
1340:            }
1341:
1342:            /**
1343:             * {@inheritDoc}
1344:             */
1345:            public Object[] getElements() {
1346:                return fMembersToMove;
1347:            }
1348:
1349:            private ITypeHierarchy getHierarchyOfDeclaringClass(
1350:                    IProgressMonitor monitor) throws JavaModelException {
1351:                try {
1352:                    if (fCachedClassHierarchy != null)
1353:                        return fCachedClassHierarchy;
1354:                    fCachedClassHierarchy = getDeclaringType()
1355:                            .newTypeHierarchy(monitor);
1356:                    return fCachedClassHierarchy;
1357:                } finally {
1358:                    monitor.done();
1359:                }
1360:            }
1361:
1362:            /**
1363:             * {@inheritDoc}
1364:             */
1365:            public String getIdentifier() {
1366:                return IDENTIFIER;
1367:            }
1368:
1369:            private MemberActionInfo[] getInfosForMembersToBeCreatedInSubclassesOfDeclaringClass()
1370:                    throws JavaModelException {
1371:                MemberActionInfo[] abs = getAbstractMemberInfos();
1372:                MemberActionInfo[] nonabs = getEffectedMemberInfos();
1373:                List result = new ArrayList(abs.length + nonabs.length);
1374:                result.addAll(Arrays.asList(abs));
1375:                result.addAll(Arrays.asList(nonabs));
1376:                return (MemberActionInfo[]) result
1377:                        .toArray(new MemberActionInfo[result.size()]);
1378:            }
1379:
1380:            public MemberActionInfo[] getMemberActionInfos() {
1381:                return fMemberInfos;
1382:            }
1383:
1384:            /**
1385:             * {@inheritDoc}
1386:             */
1387:            public String getProcessorName() {
1388:                return RefactoringCoreMessages.PushDownRefactoring_name;
1389:            }
1390:
1391:            /**
1392:             * {@inheritDoc}
1393:             */
1394:            public RefactoringStatus initialize(RefactoringArguments arguments) {
1395:                if (arguments instanceof  JavaRefactoringArguments) {
1396:                    final JavaRefactoringArguments extended = (JavaRefactoringArguments) arguments;
1397:                    String handle = extended
1398:                            .getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
1399:                    if (handle != null) {
1400:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1401:                                .handleToElement(extended.getProject(), handle,
1402:                                        false);
1403:                        if (element == null
1404:                                || !element.exists()
1405:                                || element.getElementType() != IJavaElement.TYPE)
1406:                            return ScriptableRefactoring
1407:                                    .createInputFatalStatus(element,
1408:                                            getRefactoring().getName(),
1409:                                            IJavaRefactorings.PUSH_DOWN);
1410:                        else
1411:                            fCachedDeclaringType = (IType) element;
1412:                    }
1413:                    int count = 1;
1414:                    final List elements = new ArrayList();
1415:                    final List infos = new ArrayList();
1416:                    String attribute = JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT
1417:                            + count;
1418:                    final RefactoringStatus status = new RefactoringStatus();
1419:                    while ((handle = extended.getAttribute(attribute)) != null) {
1420:                        final IJavaElement element = JavaRefactoringDescriptorUtil
1421:                                .handleToElement(extended.getProject(), handle,
1422:                                        false);
1423:                        if (element == null || !element.exists())
1424:                            status.merge(ScriptableRefactoring
1425:                                    .createInputWarningStatus(element,
1426:                                            getRefactoring().getName(),
1427:                                            IJavaRefactorings.PUSH_DOWN));
1428:                        else
1429:                            elements.add(element);
1430:                        if (extended.getAttribute(ATTRIBUTE_ABSTRACT + count) != null)
1431:                            infos.add(MemberActionInfo.create(
1432:                                    (IMember) element,
1433:                                    MemberActionInfo.PUSH_ABSTRACT_ACTION));
1434:                        else if (extended.getAttribute(ATTRIBUTE_PUSH + count) != null)
1435:                            infos.add(MemberActionInfo.create(
1436:                                    (IMember) element,
1437:                                    MemberActionInfo.PUSH_DOWN_ACTION));
1438:                        else
1439:                            infos.add(MemberActionInfo.create(
1440:                                    (IMember) element,
1441:                                    MemberActionInfo.NO_ACTION));
1442:                        count++;
1443:                        attribute = JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT
1444:                                + count;
1445:                    }
1446:                    fMembersToMove = (IMember[]) elements
1447:                            .toArray(new IMember[elements.size()]);
1448:                    fMemberInfos = (MemberActionInfo[]) infos
1449:                            .toArray(new MemberActionInfo[infos.size()]);
1450:                    if (!status.isOK())
1451:                        return status;
1452:                } else
1453:                    return RefactoringStatus
1454:                            .createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
1455:                return new RefactoringStatus();
1456:            }
1457:
1458:            /**
1459:             * {@inheritDoc}
1460:             */
1461:            public boolean isApplicable() throws CoreException {
1462:                return RefactoringAvailabilityTester
1463:                        .isPushDownAvailable(fMembersToMove);
1464:            }
1465:
1466:            /**
1467:             * {@inheritDoc}
1468:             */
1469:            protected void rewriteTypeOccurrences(
1470:                    final TextEditBasedChangeManager manager,
1471:                    final ASTRequestor requestor,
1472:                    final CompilationUnitRewrite rewrite,
1473:                    final ICompilationUnit unit, final CompilationUnit node,
1474:                    final Set replacements, final IProgressMonitor monitor)
1475:                    throws CoreException {
1476:                // Not needed
1477:            }
1478:        }
w_w__w_.___j___av___a2__s_.__com___ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.