KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > codemanipulation > AddGetterSetterOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.codemanipulation;
12
13 import org.eclipse.text.edits.TextEdit;
14
15 import org.eclipse.core.runtime.Assert;
16 import org.eclipse.core.runtime.CoreException;
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.core.runtime.IStatus;
19 import org.eclipse.core.runtime.NullProgressMonitor;
20 import org.eclipse.core.runtime.OperationCanceledException;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.core.runtime.SubProgressMonitor;
23 import org.eclipse.core.runtime.jobs.ISchedulingRule;
24
25 import org.eclipse.core.resources.IWorkspaceRunnable;
26 import org.eclipse.core.resources.ResourcesPlugin;
27
28 import org.eclipse.jdt.core.Flags;
29 import org.eclipse.jdt.core.ICompilationUnit;
30 import org.eclipse.jdt.core.IField;
31 import org.eclipse.jdt.core.IJavaElement;
32 import org.eclipse.jdt.core.IMethod;
33 import org.eclipse.jdt.core.IType;
34 import org.eclipse.jdt.core.JavaModelException;
35 import org.eclipse.jdt.core.dom.ASTNode;
36 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
37 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
38 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
39 import org.eclipse.jdt.core.dom.CompilationUnit;
40 import org.eclipse.jdt.core.dom.FieldDeclaration;
41 import org.eclipse.jdt.core.dom.MethodDeclaration;
42 import org.eclipse.jdt.core.dom.Modifier;
43 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
44 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
45 import org.eclipse.jdt.core.formatter.CodeFormatter;
46
47 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
48 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
49 import org.eclipse.jdt.internal.corext.dom.NodeFinder;
50 import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
51 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
52
53 import org.eclipse.jdt.ui.JavaUI;
54
55 /**
56  * Workspace runnable to add accessor methods to fields.
57  *
58  * @since 3.1
59  */

60 public final class AddGetterSetterOperation implements IWorkspaceRunnable {
61
62     /** The empty strings constant */
63     private static final String JavaDoc[] EMPTY_STRINGS= new String JavaDoc[0];
64
65     /** The accessor fields */
66     private final IField[] fAccessorFields;
67
68     /** Should the resulting edit be applied? */
69     private boolean fApply= true;
70
71     /** The resulting text edit */
72     private TextEdit fEdit= null;
73
74     /** The getter fields */
75     private final IField[] fGetterFields;
76
77     /** The insertion point, or <code>null</code> */
78     private final IJavaElement fInsert;
79
80     /** Should the compilation unit content be saved? */
81     private final boolean fSave;
82
83     /** The setter fields */
84     private final IField[] fSetterFields;
85
86     /** The code generation settings to use */
87     private final CodeGenerationSettings fSettings;
88
89     /** Should all existing members be skipped? */
90     private boolean fSkipAllExisting= false;
91
92     /** The skip existing request query */
93     private final IRequestQuery fSkipExistingQuery;
94
95     /** Should the accessors be sorted? */
96     private boolean fSort= false;
97
98     /** The type declaration to add the constructors to */
99     private final IType fType;
100
101     /** The compilation unit ast node */
102     private final CompilationUnit fASTRoot;
103
104     /** The visibility flags of the new accessors */
105     private int fVisibility= Modifier.PUBLIC;
106
107     /**
108      * Creates a new add getter setter operation.
109      *
110      * @param type the type to add the accessors to
111      * @param getters the fields to create getters for
112      * @param setters the fields to create setters for
113      * @param accessors the fields to create both
114      * @param unit the compilation unit ast node
115      * @param skipExistingQuery the request query
116      * @param insert the insertion point, or <code>null</code>
117      * @param settings the code generation settings to use
118      * @param apply <code>true</code> if the resulting edit should be applied, <code>false</code> otherwise
119      * @param save <code>true</code> if the changed compilation unit should be saved, <code>false</code> otherwise
120      */

121     public AddGetterSetterOperation(final IType type, final IField[] getters, final IField[] setters, final IField[] accessors, final CompilationUnit unit, final IRequestQuery skipExistingQuery, final IJavaElement insert, final CodeGenerationSettings settings, final boolean apply, final boolean save) {
122         Assert.isNotNull(type);
123         Assert.isNotNull(unit);
124         Assert.isNotNull(settings);
125         fType= type;
126         fGetterFields= getters;
127         fSetterFields= setters;
128         fAccessorFields= accessors;
129         fASTRoot= unit;
130         fSkipExistingQuery= skipExistingQuery;
131         fInsert= insert;
132         fSettings= settings;
133         fSave= save;
134         fApply= apply;
135     }
136
137     /**
138      * Adds a new accessor for the specified field.
139      *
140      * @param type the type
141      * @param field the field
142      * @param contents the contents of the accessor method
143      * @param rewrite the list rewrite to use
144      * @param insertion the insertion point
145      * @throws JavaModelException if an error occurs
146      */

147     private void addNewAccessor(final IType type, final IField field, final String JavaDoc contents, final ListRewrite rewrite, final ASTNode insertion) throws JavaModelException {
148         final String JavaDoc delimiter= StubUtility.getLineDelimiterUsed(type);
149         final MethodDeclaration declaration= (MethodDeclaration) rewrite.getASTRewrite().createStringPlaceholder(CodeFormatterUtil.format(CodeFormatter.K_CLASS_BODY_DECLARATIONS, contents, 0, null, delimiter, field.getJavaProject()), ASTNode.METHOD_DECLARATION);
150         if (insertion != null)
151             rewrite.insertBefore(declaration, insertion, null);
152         else
153             rewrite.insertLast(declaration, null);
154     }
155
156     /**
157      * Generates a new getter method for the specified field
158      *
159      * @param field the field
160      * @param rewrite the list rewrite to use
161      * @throws CoreException if an error occurs
162      * @throws OperationCanceledException if the operation has been cancelled
163      */

164     private void generateGetterMethod(final IField field, final ListRewrite rewrite) throws CoreException, OperationCanceledException {
165         final IType type= field.getDeclaringType();
166         final String JavaDoc name= GetterSetterUtil.getGetterName(field, null);
167         final IMethod existing= JavaModelUtil.findMethod(name, EMPTY_STRINGS, false, type);
168         if (existing == null || !querySkipExistingMethods(existing)) {
169             IJavaElement sibling= null;
170             if (existing != null) {
171                 sibling= StubUtility.findNextSibling(existing);
172                 removeExistingAccessor(existing, rewrite);
173             } else
174                 sibling= fInsert;
175             ASTNode insertion= null;
176             if (sibling instanceof IMethod)
177                 insertion= ASTNodes.getParent(NodeFinder.perform(rewrite.getParent().getRoot(), ((IMethod) fInsert).getNameRange()), MethodDeclaration.class);
178             addNewAccessor(type, field, GetterSetterUtil.getGetterStub(field, name, fSettings.createComments, fVisibility | (field.getFlags() & Flags.AccStatic)), rewrite, insertion);
179         }
180     }
181
182     /**
183      * Generates a new setter method for the specified field
184      *
185      * @param field the field
186      * @param astRewrite
187      * @param rewrite the list rewrite to use
188      * @throws CoreException if an error occurs
189      * @throws OperationCanceledException if the operation has been cancelled
190      */

191     private void generateSetterMethod(final IField field, ASTRewrite astRewrite, final ListRewrite rewrite) throws CoreException, OperationCanceledException {
192         final IType type= field.getDeclaringType();
193         final String JavaDoc name= GetterSetterUtil.getSetterName(field, null);
194         final IMethod existing= JavaModelUtil.findMethod(name, new String JavaDoc[] { field.getTypeSignature()}, false, type);
195         if (existing == null || querySkipExistingMethods(existing)) {
196             IJavaElement sibling= null;
197             if (existing != null) {
198                 sibling= StubUtility.findNextSibling(existing);
199                 removeExistingAccessor(existing, rewrite);
200             } else
201                 sibling= fInsert;
202             ASTNode insertion= null;
203             if (sibling instanceof IMethod)
204                 insertion= ASTNodes.getParent(NodeFinder.perform(fASTRoot, ((IMethod) fInsert).getNameRange()), MethodDeclaration.class);
205             addNewAccessor(type, field, GetterSetterUtil.getSetterStub(field, name, fSettings.createComments, fVisibility | (field.getFlags() & Flags.AccStatic)), rewrite, insertion);
206             if (Flags.isFinal(field.getFlags())) {
207                 ASTNode fieldDecl= ASTNodes.getParent(NodeFinder.perform(fASTRoot, field.getNameRange()), FieldDeclaration.class);
208                 if (fieldDecl != null) {
209                     ModifierRewrite.create(astRewrite, fieldDecl).setModifiers(0, Modifier.FINAL, null);
210                 }
211             }
212             
213         }
214     }
215
216     /**
217      * Returns the resulting text edit.
218      *
219      * @return the resulting text edit
220      */

221     public final TextEdit getResultingEdit() {
222         return fEdit;
223     }
224
225     /**
226      * Returns the scheduling rule for this operation.
227      *
228      * @return the scheduling rule
229      */

230     public final ISchedulingRule getSchedulingRule() {
231         return ResourcesPlugin.getWorkspace().getRoot();
232     }
233
234     /**
235      * Returns the visibility modifier of the generated constructors.
236      *
237      * @return the visibility modifier
238      */

239     public final int getVisibility() {
240         return fVisibility;
241     }
242
243     /**
244      * Should all existing members be skipped?
245      *
246      * @return <code>true</code> if they should be skipped, <code>false</code> otherwise
247      */

248     public final boolean isSkipAllExisting() {
249         return fSkipAllExisting;
250     }
251
252     /**
253      * Queries the user whether to skip existing methods.
254      *
255      * @param method the method in question
256      * @return <code>true</code> to skip existing methods, <code>false</code> otherwise
257      * @throws OperationCanceledException if the operation has been cancelled
258      */

259     private boolean querySkipExistingMethods(final IMethod method) throws OperationCanceledException {
260         if (!fSkipAllExisting) {
261             switch (fSkipExistingQuery.doQuery(method)) {
262                 case IRequestQuery.CANCEL:
263                     throw new OperationCanceledException();
264                 case IRequestQuery.NO:
265                     return false;
266                 case IRequestQuery.YES_ALL:
267                     fSkipAllExisting= true;
268             }
269         }
270         return true;
271     }
272
273     /**
274      * Removes an existing accessor method.
275      *
276      * @param accessor the accessor method to remove
277      * @param rewrite the list rewrite to use
278      * @throws JavaModelException if an error occurs
279      */

280     private void removeExistingAccessor(final IMethod accessor, final ListRewrite rewrite) throws JavaModelException {
281         final MethodDeclaration declaration= (MethodDeclaration) ASTNodes.getParent(NodeFinder.perform(rewrite.getParent().getRoot(), accessor.getNameRange()), MethodDeclaration.class);
282         if (declaration != null)
283             rewrite.remove(declaration, null);
284     }
285
286     /*
287      * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
288      */

289     public final void run(IProgressMonitor monitor) throws CoreException {
290         if (monitor == null)
291             monitor= new NullProgressMonitor();
292         try {
293             monitor.setTaskName(CodeGenerationMessages.AddGetterSetterOperation_description);
294             monitor.beginTask("", fGetterFields.length + fSetterFields.length); //$NON-NLS-1$
295
final ICompilationUnit unit= fType.getCompilationUnit();
296             final ASTRewrite astRewrite= ASTRewrite.create(fASTRoot.getAST());
297             ListRewrite listRewriter= null;
298             if (fType.isAnonymous()) {
299                 final ClassInstanceCreation creation= (ClassInstanceCreation) ASTNodes.getParent(NodeFinder.perform(fASTRoot, fType.getNameRange()), ClassInstanceCreation.class);
300                 if (creation != null) {
301                     final AnonymousClassDeclaration declaration= creation.getAnonymousClassDeclaration();
302                     if (declaration != null)
303                         listRewriter= astRewrite.getListRewrite(declaration, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY);
304                 }
305             } else {
306                 final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) ASTNodes.getParent(NodeFinder.perform(fASTRoot, fType.getNameRange()), AbstractTypeDeclaration.class);
307                 if (declaration != null)
308                     listRewriter= astRewrite.getListRewrite(declaration, declaration.getBodyDeclarationsProperty());
309             }
310             if (listRewriter == null) {
311                 throw new CoreException(new Status(IStatus.ERROR, JavaUI.ID_PLUGIN, IStatus.ERROR, CodeGenerationMessages.AddGetterSetterOperation_error_input_type_not_found, null));
312             }
313             
314             fSkipAllExisting= (fSkipExistingQuery == null);
315             if (!fSort) {
316                 for (int index= 0; index < fAccessorFields.length; index++) {
317                     generateGetterMethod(fAccessorFields[index], listRewriter);
318                     generateSetterMethod(fAccessorFields[index], astRewrite, listRewriter);
319                     monitor.worked(1);
320                     if (monitor.isCanceled()) {
321                         throw new OperationCanceledException();
322                     }
323                 }
324             }
325             for (int index= 0; index < fGetterFields.length; index++) {
326                 generateGetterMethod(fGetterFields[index], listRewriter);
327                 monitor.worked(1);
328                 if (monitor.isCanceled()) {
329                     throw new OperationCanceledException();
330                 }
331             }
332             for (int index= 0; index < fSetterFields.length; index++) {
333                 generateSetterMethod(fSetterFields[index], astRewrite, listRewriter);
334                 monitor.worked(1);
335                 if (monitor.isCanceled()) {
336                     throw new OperationCanceledException();
337                 }
338             }
339             fEdit= astRewrite.rewriteAST();
340             if (fApply) {
341                 JavaModelUtil.applyEdit(unit, fEdit, fSave, new SubProgressMonitor(monitor, 1));
342             }
343         } finally {
344             monitor.done();
345         }
346     }
347
348     /**
349      * Determines whether existing members should be skipped.
350      *
351      * @param skip <code>true</code> to skip existing members, <code>false</code> otherwise
352      */

353     public final void setSkipAllExisting(final boolean skip) {
354         fSkipAllExisting= skip;
355     }
356
357     public void setSort(boolean sort) {
358         fSort= sort;
359     }
360
361     /**
362      * Sets the visibility modifier of the generated constructors.
363      *
364      * @param visibility the visibility modifier
365      */

366     public final void setVisibility(final int visibility) {
367         fVisibility= visibility;
368     }
369 }
370
Popular Tags