KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > CreateElementInCUOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.core;
12
13 import java.util.Map JavaDoc;
14
15 import org.eclipse.core.resources.IResource;
16 import org.eclipse.core.resources.IWorkspace;
17 import org.eclipse.core.runtime.jobs.ISchedulingRule;
18 import org.eclipse.jdt.core.ICompilationUnit;
19 import org.eclipse.jdt.core.IJavaElement;
20 import org.eclipse.jdt.core.IJavaModelStatus;
21 import org.eclipse.jdt.core.IJavaModelStatusConstants;
22 import org.eclipse.jdt.core.JavaModelException;
23 import org.eclipse.jdt.core.dom.AST;
24 import org.eclipse.jdt.core.dom.ASTNode;
25 import org.eclipse.jdt.core.dom.ASTParser;
26 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
27 import org.eclipse.jdt.core.dom.CompilationUnit;
28 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
29 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
30 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
31 import org.eclipse.jdt.internal.core.util.Util;
32 import org.eclipse.jface.text.BadLocationException;
33 import org.eclipse.jface.text.IDocument;
34 import org.eclipse.text.edits.TextEdit;
35
36 /**
37  * <p>This abstract class implements behavior common to <code>CreateElementInCUOperations</code>.
38  * To create a compilation unit, or an element contained in a compilation unit, the
39  * source code for the entire compilation unit is updated and saved.
40  *
41  * <p>The element being created can be positioned relative to an existing
42  * element in the compilation unit via the methods <code>#createAfter</code>
43  * and <code>#createBefore</code>. By default, the new element is positioned
44  * as the last child of its parent element.
45  *
46  */

47 public abstract class CreateElementInCUOperation extends JavaModelOperation {
48     /**
49      * The compilation unit AST used for this operation
50      */

51     protected CompilationUnit cuAST;
52     /**
53      * A constant meaning to position the new element
54      * as the last child of its parent element.
55      */

56     protected static final int INSERT_LAST = 1;
57     /**
58      * A constant meaning to position the new element
59      * after the element defined by <code>fAnchorElement</code>.
60      */

61     protected static final int INSERT_AFTER = 2;
62
63     /**
64      * A constant meaning to position the new element
65      * before the element defined by <code>fAnchorElement</code>.
66      */

67     protected static final int INSERT_BEFORE = 3;
68     /**
69      * One of the position constants, describing where
70      * to position the newly created element.
71      */

72     protected int insertionPolicy = INSERT_LAST;
73     /**
74      * The element that the newly created element is
75      * positioned relative to, as described by
76      * <code>fInsertPosition</code>, or <code>null</code>
77      * if the newly created element will be positioned
78      * last.
79      */

80     protected IJavaElement anchorElement = null;
81     /**
82      * A flag indicating whether creation of a new element occurred.
83      * A request for creating a duplicate element would request in this
84      * flag being set to <code>false</code>. Ensures that no deltas are generated
85      * when creation does not occur.
86      */

87     protected boolean creationOccurred = true;
88     /**
89      * Constructs an operation that creates a Java Language Element with
90      * the specified parent, contained within a compilation unit.
91      */

92     public CreateElementInCUOperation(IJavaElement parentElement) {
93         super(null, new IJavaElement[]{parentElement});
94         initializeDefaultPosition();
95     }
96     protected void apply(ASTRewrite rewriter, IDocument document, Map JavaDoc options) throws JavaModelException {
97         TextEdit edits = rewriter.rewriteAST(document, options);
98         try {
99             edits.apply(document);
100         } catch (BadLocationException e) {
101             throw new JavaModelException(e, IJavaModelStatusConstants.INVALID_CONTENTS);
102         }
103     }
104     /**
105      * Only allow cancelling if this operation is not nested.
106      */

107     protected void checkCanceled() {
108         if (!isNested) {
109             super.checkCanceled();
110         }
111     }
112     /**
113      * Instructs this operation to position the new element after
114      * the given sibling, or to add the new element as the last child
115      * of its parent if <code>null</code>.
116      */

117     public void createAfter(IJavaElement sibling) {
118         setRelativePosition(sibling, INSERT_AFTER);
119     }
120     /**
121      * Instructs this operation to position the new element before
122      * the given sibling, or to add the new element as the last child
123      * of its parent if <code>null</code>.
124      */

125     public void createBefore(IJavaElement sibling) {
126         setRelativePosition(sibling, INSERT_BEFORE);
127     }
128     /**
129      * Execute the operation - generate new source for the compilation unit
130      * and save the results.
131      *
132      * @exception JavaModelException if the operation is unable to complete
133      */

134     protected void executeOperation() throws JavaModelException {
135         try {
136             beginTask(getMainTaskName(), getMainAmountOfWork());
137             JavaElementDelta delta = newJavaElementDelta();
138             ICompilationUnit unit = getCompilationUnit();
139             generateNewCompilationUnitAST(unit);
140             if (this.creationOccurred) {
141                 //a change has really occurred
142
unit.save(null, false);
143                 boolean isWorkingCopy = unit.isWorkingCopy();
144                 if (!isWorkingCopy)
145                     setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
146                 worked(1);
147                 resultElements = generateResultHandles();
148                 if (!isWorkingCopy // if unit is working copy, then save will have already fired the delta
149
&& !Util.isExcluded(unit)
150                         && unit.getParent().exists()) {
151                     for (int i = 0; i < resultElements.length; i++) {
152                         delta.added(resultElements[i]);
153                     }
154                     addDelta(delta);
155                 } // else unit is created outside classpath
156
// non-java resource delta will be notified by delta processor
157
}
158         } finally {
159             done();
160         }
161     }
162     
163     /*
164      * Returns the property descriptor for the element being created.
165      */

166     protected abstract StructuralPropertyDescriptor getChildPropertyDescriptor(ASTNode parent);
167     
168     /*
169      * Returns an AST node for the element being created.
170      */

171     protected abstract ASTNode generateElementAST(ASTRewrite rewriter, IDocument document, ICompilationUnit cu) throws JavaModelException;
172     /*
173      * Generates a new AST for this operation and applies it to the given cu
174      */

175     protected void generateNewCompilationUnitAST(ICompilationUnit cu) throws JavaModelException {
176         this.cuAST = parse(cu);
177         
178         AST ast = this.cuAST.getAST();
179         ASTRewrite rewriter = ASTRewrite.create(ast);
180         IDocument document = getDocument(cu);
181         ASTNode child = generateElementAST(rewriter, document, cu);
182         if (child != null) {
183             ASTNode parent = ((JavaElement) getParentElement()).findNode(this.cuAST);
184             if (parent == null)
185                 parent = this.cuAST;
186             insertASTNode(rewriter, parent, child);
187             apply(rewriter, document, cu.getJavaProject().getOptions(true));
188         }
189         worked(1);
190     }
191     /**
192      * Creates and returns the handle for the element this operation created.
193      */

194     protected abstract IJavaElement generateResultHandle();
195     /**
196      * Creates and returns the handles for the elements this operation created.
197      */

198     protected IJavaElement[] generateResultHandles() {
199         return new IJavaElement[]{generateResultHandle()};
200     }
201     /**
202      * Returns the compilation unit in which the new element is being created.
203      */

204     protected ICompilationUnit getCompilationUnit() {
205         return getCompilationUnitFor(getParentElement());
206     }
207     /**
208      * Returns the amount of work for the main task of this operation for
209      * progress reporting.
210      */

211     protected int getMainAmountOfWork(){
212         return 2;
213     }
214     /**
215      * Returns the name of the main task of this operation for
216      * progress reporting.
217      */

218     public abstract String JavaDoc getMainTaskName();
219
220     protected ISchedulingRule getSchedulingRule() {
221         IResource resource = getCompilationUnit().getResource();
222         IWorkspace workspace = resource.getWorkspace();
223         return workspace.getRuleFactory().modifyRule(resource);
224     }
225     /**
226      * Sets the default position in which to create the new type
227      * member.
228      * Operations that require a different default position must
229      * override this method.
230      */

231     protected void initializeDefaultPosition() {
232         // By default, the new element is positioned as the
233
// last child of the parent element in which it is created.
234
}
235     /**
236      * Inserts the given child into the given AST,
237      * based on the position settings of this operation.
238      *
239      * @see #createAfter(IJavaElement)
240      * @see #createBefore(IJavaElement)
241      */

242     protected void insertASTNode(ASTRewrite rewriter, ASTNode parent, ASTNode child) throws JavaModelException {
243         StructuralPropertyDescriptor propertyDescriptor = getChildPropertyDescriptor(parent);
244         if (propertyDescriptor instanceof ChildListPropertyDescriptor) {
245             ChildListPropertyDescriptor childListPropertyDescriptor = (ChildListPropertyDescriptor) propertyDescriptor;
246             ListRewrite rewrite = rewriter.getListRewrite(parent, childListPropertyDescriptor);
247             switch (this.insertionPolicy) {
248                 case INSERT_BEFORE:
249                     ASTNode element = ((JavaElement) this.anchorElement).findNode(this.cuAST);
250                     if (childListPropertyDescriptor.getElementType().isAssignableFrom(element.getClass()))
251                         rewrite.insertBefore(child, element, null);
252                     else
253                         // case of an empty import list: the anchor element is the top level type and cannot be used in insertBefore as it is not the same type
254
rewrite.insertLast(child, null);
255                     break;
256                 case INSERT_AFTER:
257                     element = ((JavaElement) this.anchorElement).findNode(this.cuAST);
258                     if (childListPropertyDescriptor.getElementType().isAssignableFrom(element.getClass()))
259                         rewrite.insertAfter(child, element, null);
260                     else
261                         // case of an empty import list: the anchor element is the top level type and cannot be used in insertAfter as it is not the same type
262
rewrite.insertLast(child, null);
263                     break;
264                 case INSERT_LAST:
265                     rewrite.insertLast(child, null);
266                     break;
267             }
268         } else {
269             rewriter.set(parent, propertyDescriptor, child, null);
270         }
271     }
272     protected CompilationUnit parse(ICompilationUnit cu) throws JavaModelException {
273         // ensure cu is consistent (noop if already consistent)
274
cu.makeConsistent(this.progressMonitor);
275         // create an AST for the compilation unit
276
ASTParser parser = ASTParser.newParser(AST.JLS3);
277         parser.setSource(cu);
278         return (CompilationUnit) parser.createAST(this.progressMonitor);
279     }
280     /**
281      * Sets the name of the <code>DOMNode</code> that will be used to
282      * create this new element.
283      * Used by the <code>CopyElementsOperation</code> for renaming.
284      * Only used for <code>CreateTypeMemberOperation</code>
285      */

286     protected void setAlteredName(String JavaDoc newName) {
287         // implementation in CreateTypeMemberOperation
288
}
289     /**
290      * Instructs this operation to position the new element relative
291      * to the given sibling, or to add the new element as the last child
292      * of its parent if <code>null</code>. The <code>position</code>
293      * must be one of the position constants.
294      */

295     protected void setRelativePosition(IJavaElement sibling, int policy) throws IllegalArgumentException JavaDoc {
296         if (sibling == null) {
297             this.anchorElement = null;
298             this.insertionPolicy = INSERT_LAST;
299         } else {
300             this.anchorElement = sibling;
301             this.insertionPolicy = policy;
302         }
303     }
304     /**
305      * Possible failures: <ul>
306      * <li>NO_ELEMENTS_TO_PROCESS - the compilation unit supplied to the operation is
307      * <code>null</code>.
308      * <li>INVALID_NAME - no name, a name was null or not a valid
309      * import declaration name.
310      * <li>INVALID_SIBLING - the sibling provided for positioning is not valid.
311      * </ul>
312      * @see IJavaModelStatus
313      * @see org.eclipse.jdt.core.JavaConventions
314      */

315     public IJavaModelStatus verify() {
316         if (getParentElement() == null) {
317             return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
318         }
319         if (this.anchorElement != null) {
320             IJavaElement domPresentParent = this.anchorElement.getParent();
321             if (domPresentParent.getElementType() == IJavaElement.IMPORT_CONTAINER) {
322                 domPresentParent = domPresentParent.getParent();
323             }
324             if (!domPresentParent.equals(getParentElement())) {
325                 return new JavaModelStatus(IJavaModelStatusConstants.INVALID_SIBLING, this.anchorElement);
326             }
327         }
328         return JavaModelStatus.VERIFIED_OK;
329     }
330 }
331
Popular Tags