KickJava   Java API By Example, From Geeks To Geeks.

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


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.HashMap JavaDoc;
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.core.runtime.IPath;
17 import org.eclipse.jdt.core.ICompilationUnit;
18 import org.eclipse.jdt.core.IImportDeclaration;
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.IMember;
23 import org.eclipse.jdt.core.IParent;
24 import org.eclipse.jdt.core.IType;
25 import org.eclipse.jdt.core.JavaModelException;
26 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
27 import org.eclipse.jdt.internal.core.util.Messages;
28
29 /**
30  * This operation copies/moves a collection of elements from their current
31  * container to a new container, optionally renaming the
32  * elements.
33  * <p>Notes:<ul>
34  * <li>If there is already an element with the same name in
35  * the new container, the operation either overwrites or aborts,
36  * depending on the collision policy setting. The default setting is
37  * abort.
38  *
39  * <li>When constructors are copied to a type, the constructors
40  * are automatically renamed to the name of the destination
41  * type.
42  *
43  * <li>When main types are renamed (move within the same parent),
44  * the compilation unit and constructors are automatically renamed
45  *
46  * <li>The collection of elements being copied must all share the
47  * same type of container (for example, must all be type members).
48  *
49  * <li>The elements are inserted in the new container in the order given.
50  *
51  * <li>The elements can be positioned in the new container - see #setInsertBefore.
52  * By default, the elements are inserted based on the default positions as specified in
53  * the creation operation for that element type.
54  *
55  * <li>This operation can be used to copy and rename elements within
56  * the same container.
57  *
58  * <li>This operation only copies elements contained within compilation units.
59  * </ul>
60  *
61  */

62 public class CopyElementsOperation extends MultiOperation implements SuffixConstants {
63
64     
65     private Map JavaDoc sources = new HashMap JavaDoc();
66 /**
67  * When executed, this operation will copy the given elements to the
68  * given containers. The elements and destination containers must be in
69  * the correct order. If there is > 1 destination, the number of destinations
70  * must be the same as the number of elements being copied/moved/renamed.
71  */

72 public CopyElementsOperation(IJavaElement[] elementsToCopy, IJavaElement[] destContainers, boolean force) {
73     super(elementsToCopy, destContainers, force);
74 }
75 /**
76  * When executed, this operation will copy the given elements to the
77  * given container.
78  */

79 public CopyElementsOperation(IJavaElement[] elementsToCopy, IJavaElement destContainer, boolean force) {
80     this(elementsToCopy, new IJavaElement[]{destContainer}, force);
81 }
82 /**
83  * Returns the <code>String</code> to use as the main task name
84  * for progress monitoring.
85  */

86 protected String JavaDoc getMainTaskName() {
87     return Messages.operation_copyElementProgress;
88 }
89 /**
90  * Returns the nested operation to use for processing this element
91  */

92 protected JavaModelOperation getNestedOperation(IJavaElement element) {
93     try {
94         IJavaElement dest = getDestinationParent(element);
95         switch (element.getElementType()) {
96             case IJavaElement.PACKAGE_DECLARATION :
97                 return new CreatePackageDeclarationOperation(element.getElementName(), (ICompilationUnit) dest);
98             case IJavaElement.IMPORT_DECLARATION :
99                 IImportDeclaration importDeclaration = (IImportDeclaration) element;
100                 return new CreateImportOperation(element.getElementName(), (ICompilationUnit) dest, importDeclaration.getFlags());
101             case IJavaElement.TYPE :
102                 if (isRenamingMainType(element, dest)) {
103                     IPath path = element.getPath();
104                     String JavaDoc extension = path.getFileExtension();
105                     return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String JavaDoc[]{getNewNameFor(element) + '.' + extension}, this.force);
106                 } else {
107                     String JavaDoc source = getSourceFor(element);
108                     String JavaDoc lineSeparator = org.eclipse.jdt.internal.core.util.Util.getLineSeparator(source, element.getJavaProject());
109                     return new CreateTypeOperation(dest, source + lineSeparator, this.force);
110                 }
111             case IJavaElement.METHOD :
112                 String JavaDoc source = getSourceFor(element);
113                 String JavaDoc lineSeparator = org.eclipse.jdt.internal.core.util.Util.getLineSeparator(source, element.getJavaProject());
114                 return new CreateMethodOperation((IType) dest, source + lineSeparator, this.force);
115             case IJavaElement.FIELD :
116                 source = getSourceFor(element);
117                 lineSeparator = org.eclipse.jdt.internal.core.util.Util.getLineSeparator(source, element.getJavaProject());
118                 return new CreateFieldOperation((IType) dest, source + lineSeparator, this.force);
119             case IJavaElement.INITIALIZER :
120                 source = getSourceFor(element);
121                 lineSeparator = org.eclipse.jdt.internal.core.util.Util.getLineSeparator(source, element.getJavaProject());
122                 return new CreateInitializerOperation((IType) dest, source + lineSeparator);
123             default :
124                 return null;
125         }
126     } catch (JavaModelException npe) {
127         return null;
128     }
129 }
130 /**
131  * Returns the cached source for this element or compute it if not already cached.
132  */

133 private String JavaDoc getSourceFor(IJavaElement element) throws JavaModelException {
134     String JavaDoc source = (String JavaDoc) this.sources.get(element);
135     if (source == null && element instanceof IMember) {
136         source = ((IMember)element).getSource();
137         this.sources.put(element, source);
138     }
139     return source;
140 }
141 /**
142  * Returns <code>true</code> if this element is the main type of its compilation unit.
143  */

144 protected boolean isRenamingMainType(IJavaElement element, IJavaElement dest) throws JavaModelException {
145     if ((isRename() || getNewNameFor(element) != null)
146         && dest.getElementType() == IJavaElement.COMPILATION_UNIT) {
147         String JavaDoc typeName = dest.getElementName();
148         typeName = org.eclipse.jdt.internal.core.util.Util.getNameWithoutJavaLikeExtension(typeName);
149         return element.getElementName().equals(typeName) && element.getParent().equals(dest);
150     }
151     return false;
152 }
153 /**
154  * Copy/move the element from the source to destination, renaming
155  * the elements as specified, honoring the collision policy.
156  *
157  * @exception JavaModelException if the operation is unable to
158  * be completed
159  */

160 protected void processElement(IJavaElement element) throws JavaModelException {
161     JavaModelOperation op = getNestedOperation(element);
162     boolean createElementInCUOperation =op instanceof CreateElementInCUOperation;
163     if (op == null) {
164         return;
165     }
166     if (createElementInCUOperation) {
167         IJavaElement sibling = (IJavaElement) this.insertBeforeElements.get(element);
168         if (sibling != null) {
169             ((CreateElementInCUOperation) op).setRelativePosition(sibling, CreateElementInCUOperation.INSERT_BEFORE);
170         } else
171             if (isRename()) {
172                 IJavaElement anchor = resolveRenameAnchor(element);
173                 if (anchor != null) {
174                     ((CreateElementInCUOperation) op).setRelativePosition(anchor, CreateElementInCUOperation.INSERT_AFTER); // insert after so that the anchor is found before when deleted below
175
}
176             }
177         String JavaDoc newName = getNewNameFor(element);
178         if (newName != null) {
179             ((CreateElementInCUOperation) op).setAlteredName(newName);
180         }
181     }
182     executeNestedOperation(op, 1);
183
184     JavaElement destination = (JavaElement) getDestinationParent(element);
185     ICompilationUnit unit= destination.getCompilationUnit();
186     if (!unit.isWorkingCopy()) {
187         unit.close();
188     }
189
190     if (createElementInCUOperation && isMove() && !isRenamingMainType(element, destination)) {
191         DeleteElementsOperation deleteOp = new DeleteElementsOperation(new IJavaElement[] { element }, this.force);
192         executeNestedOperation(deleteOp, 1);
193     }
194 }
195 /**
196  * Returns the anchor used for positioning in the destination for
197  * the element being renamed. For renaming, if no anchor has
198  * explicitly been provided, the element is anchored in the same position.
199  */

200 private IJavaElement resolveRenameAnchor(IJavaElement element) throws JavaModelException {
201     IParent parent = (IParent) element.getParent();
202     IJavaElement[] children = parent.getChildren();
203     for (int i = 0; i < children.length; i++) {
204         IJavaElement child = children[i];
205         if (child.equals(element)) {
206             return child;
207         }
208     }
209     return null;
210 }
211 /**
212  * Possible failures:
213  * <ul>
214  * <li>NO_ELEMENTS_TO_PROCESS - no elements supplied to the operation
215  * <li>INDEX_OUT_OF_BOUNDS - the number of renamings supplied to the operation
216  * does not match the number of elements that were supplied.
217  * </ul>
218  */

219 protected IJavaModelStatus verify() {
220     IJavaModelStatus status = super.verify();
221     if (!status.isOK()) {
222         return status;
223     }
224     if (this.renamingsList != null && this.renamingsList.length != this.elementsToProcess.length) {
225         return new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS);
226     }
227     return JavaModelStatus.VERIFIED_OK;
228 }
229 /**
230  * @see MultiOperation
231  *
232  * Possible failure codes:
233  * <ul>
234  *
235  * <li>ELEMENT_DOES_NOT_EXIST - <code>element</code> or its specified destination is
236  * is <code>null</code> or does not exist. If a <code>null</code> element is
237  * supplied, no element is provided in the status, otherwise, the non-existant element
238  * is supplied in the status.
239  * <li>INVALID_ELEMENT_TYPES - <code>element</code> is not contained within a compilation unit.
240  * This operation only operates on elements contained within compilation units.
241  * <li>READ_ONLY - <code>element</code> is read only.
242  * <li>INVALID_DESTINATION - The destination parent specified for <code>element</code>
243  * is of an incompatible type. The destination for a package declaration or import declaration must
244  * be a compilation unit; the destination for a type must be a type or compilation
245  * unit; the destinaion for any type member (other than a type) must be a type. When
246  * this error occurs, the element provided in the operation status is the <code>element</code>.
247  * <li>INVALID_NAME - the new name for <code>element</code> does not have valid syntax.
248  * In this case the element and name are provided in the status.
249
250  * </ul>
251  */

252 protected void verify(IJavaElement element) throws JavaModelException {
253     if (element == null || !element.exists())
254         error(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element);
255
256     if (element.getElementType() < IJavaElement.TYPE)
257         error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
258
259     if (element.isReadOnly())
260         error(IJavaModelStatusConstants.READ_ONLY, element);
261
262     IJavaElement dest = getDestinationParent(element);
263     verifyDestination(element, dest);
264     verifySibling(element, dest);
265     if (this.renamingsList != null) {
266         verifyRenaming(element);
267     }
268 }
269 }
270
Popular Tags