1 /*******************************************************************************
2  * Copyright (c) 2007, 2008 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.corext.refactoring;
15 
16 import org.eclipse.core.runtime.Assert;
17 import org.eclipse.core.runtime.IPath;
18 import org.eclipse.core.runtime.Path;
19 
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.IWorkspaceRoot;
22 import org.eclipse.core.resources.ResourcesPlugin;
23 
24 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
25 
26 import org.eclipse.jdt.core.IJavaElement;
27 import org.eclipse.jdt.core.IJavaProject;
28 import org.eclipse.jdt.core.IMethod;
29 import org.eclipse.jdt.core.JavaCore;
30 import org.eclipse.jdt.core.WorkingCopyOwner;
31 
32 import org.eclipse.jdt.internal.core.manipulation.JavaElementLabelsCore;
33 import org.eclipse.jdt.internal.corext.util.Messages;
34 
35 public class JavaRefactoringDescriptorUtil {
36 	/* TODO: share implementation with
37 	 * org.eclipse.jdt.internal.core.refactoring.descriptors.JavaRefactoringDescriptorUtil
38 	 */
39 
JavaRefactoringDescriptorUtil()40 	private JavaRefactoringDescriptorUtil(){}
41 
42 	/**
43 	 * Predefined argument called <code>element&lt;Number&gt;</code>.
44 	 * <p>
45 	 * This argument should be used to describe the elements being refactored.
46 	 * The value of this argument does not necessarily have to uniquely identify
47 	 * the elements. However, it must be possible to uniquely identify the
48 	 * elements using the value of this argument in conjunction with the values
49 	 * of the other user-defined attributes.
50 	 * </p>
51 	 * <p>
52 	 * The element arguments are simply distinguished by appending a number to
53 	 * the argument name, e.g. element1. The indices of this argument are non
54 	 * zero-based.
55 	 * </p>
56 	 */
57 	public static final String ATTRIBUTE_ELEMENT= "element"; //$NON-NLS-1$
58 
59 	/**
60 	 * Predefined argument called <code>input</code>.
61 	 * <p>
62 	 * This argument should be used to describe the element being refactored.
63 	 * The value of this argument does not necessarily have to uniquely identify
64 	 * the input element. However, it must be possible to uniquely identify the
65 	 * input element using the value of this argument in conjunction with the
66 	 * values of the other user-defined attributes.
67 	 * </p>
68 	 */
69 	public static final String ATTRIBUTE_INPUT= "input"; //$NON-NLS-1$
70 
71 	/**
72 	 * Predefined argument called <code>name</code>.
73 	 * <p>
74 	 * This argument should be used to name the element being refactored. The
75 	 * value of this argument may be shown in the user interface.
76 	 * </p>
77 	 */
78 	public static final String ATTRIBUTE_NAME= "name"; //$NON-NLS-1$
79 
80 	/**
81 	 * Predefined argument called <code>references</code>.
82 	 * <p>
83 	 * This argument should be used to describe whether references to the
84 	 * elements being refactored should be updated as well.
85 	 * </p>
86 	 */
87 	public static final String ATTRIBUTE_REFERENCES= "references"; //$NON-NLS-1$
88 
89 	/**
90 	 * Predefined argument called <code>selection</code>.
91 	 * <p>
92 	 * This argument should be used to describe user input selections within a
93 	 * text file. The value of this argument has the format "offset length".
94 	 * </p>
95 	 */
96 	public static final String ATTRIBUTE_SELECTION= "selection"; //$NON-NLS-1$
97 
98 	/**
99 	 * Converts the specified element to an input handle.
100 	 *
101 	 * @param project
102 	 *            the project, or <code>null</code> for the workspace
103 	 * @param element
104 	 *            the element
105 	 * @return a corresponding input handle
106 	 *         Note: if the given project is not the element's project, then the full handle is returned
107 	 */
elementToHandle(final String project, final IJavaElement element)108 	public static String elementToHandle(final String project, final IJavaElement element) {
109 		final String handle= element.getHandleIdentifier();
110 		if (project != null && ! (element instanceof IJavaProject)) {
111 			IJavaProject javaProject= element.getJavaProject();
112 			if (project.equals(javaProject.getElementName())) {
113 				final String id= javaProject.getHandleIdentifier();
114 				return handle.substring(id.length());
115 			}
116 		}
117 		return handle;
118 	}
119 
120 	/**
121 	 * Converts an input handle back to the corresponding java element.
122 	 *
123 	 * @param project
124 	 *            the project, or <code>null</code> for the workspace
125 	 * @param handle
126 	 *            the input handle
127 	 * @return the corresponding java element, or <code>null</code> if no such
128 	 *         element exists
129 	 */
handleToElement(final String project, final String handle)130 	public static IJavaElement handleToElement(final String project, final String handle) {
131 		return handleToElement(project, handle, true);
132 	}
133 
134 	/**
135 	 * Converts an input handle back to the corresponding java element.
136 	 *
137 	 * @param project
138 	 *            the project, or <code>null</code> for the workspace
139 	 * @param handle
140 	 *            the input handle
141 	 * @param check
142 	 *            <code>true</code> to check for existence of the element,
143 	 *            <code>false</code> otherwise
144 	 * @return the corresponding java element, or <code>null</code> if no such
145 	 *         element exists
146 	 */
handleToElement(final String project, final String handle, final boolean check)147 	public static IJavaElement handleToElement(final String project, final String handle, final boolean check) {
148 		return handleToElement(null, project, handle, check);
149 	}
150 
151 	/**
152 	 * Converts an input handle back to the corresponding java element.
153 	 *
154 	 * @param owner
155 	 *            the working copy owner
156 	 * @param project
157 	 *            the project, or <code>null</code> for the workspace
158 	 * @param handle
159 	 *            the input handle
160 	 * @param check
161 	 *            <code>true</code> to check for existence of the element,
162 	 *            <code>false</code> otherwise
163 	 * @return the corresponding java element, or <code>null</code> if no such
164 	 *         element exists
165 	 */
handleToElement(final WorkingCopyOwner owner, final String project, final String handle, final boolean check)166 	public static IJavaElement handleToElement(final WorkingCopyOwner owner, final String project, final String handle, final boolean check) {
167 		IJavaElement element= null;
168 		if (owner != null)
169 			element= JavaCore.create(handle, owner);
170 		else
171 			element= JavaCore.create(handle);
172 		if (element == null && project != null) {
173 			final IJavaProject javaProject= JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProject(project);
174 			final String identifier= javaProject.getHandleIdentifier();
175 			if (owner != null)
176 				element= JavaCore.create(identifier + handle, owner);
177 			else
178 				element= JavaCore.create(identifier + handle);
179 		}
180 		if (check && element instanceof IMethod) {
181 			/*
182 			 * Resolve the method based on simple names of parameter types
183 			 * (to accommodate for different qualifications when refactoring is e.g.
184 			 * recorded in source but applied on binary method):
185 			 */
186 			final IMethod method= (IMethod) element;
187 			final IMethod[] methods= method.getDeclaringType().findMethods(method);
188 			if (methods != null && methods.length > 0)
189 				element= methods[0];
190 		}
191 		if (element != null && (!check || element.exists()))
192 			return element;
193 		return null;
194 	}
195 
196 	/**
197 	 * Converts an input handle with the given prefix back to the corresponding
198 	 * resource.
199 	 *
200 	 * @param project
201 	 *            the project, or <code>null</code> for the workspace
202 	 * @param handle
203 	 *            the input handle
204 	 *
205 	 * @return the corresponding resource, or <code>null</code> if no such
206 	 *         resource exists.
207 	 *         Note: if the given handle is absolute, the project is not used to resolve.
208 	 */
handleToResource(final String project, final String handle)209 	public static IResource handleToResource(final String project, final String handle) {
210 		final IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
211 		if ("".equals(handle)) //$NON-NLS-1$
212 			return null;
213 		final IPath path= Path.fromPortableString(handle);
214 		if (path == null)
215 			return null;
216 		if (project != null && !"".equals(project) && ! path.isAbsolute()) //$NON-NLS-1$
217 			return root.getProject(project).findMember(path);
218 		return root.findMember(path);
219 	}
220 
221 	/**
222 	 * Converts the specified resource to an input handle.
223 	 *
224 	 * @param project
225 	 *            the project, or <code>null</code> for the workspace
226 	 * @param resource
227 	 *            the resource
228 	 *
229 	 * @return the input handle.
230 	 *         Note: if the given project is not the resource's project, then the full handle is returned.
231 	 */
resourceToHandle(final String project, final IResource resource)232 	public static String resourceToHandle(final String project, final IResource resource) {
233 		if (project != null && !"".equals(project) && project.equals(resource.getProject().getName())) //$NON-NLS-1$
234 			return resource.getProjectRelativePath().toPortableString();
235 		return resource.getFullPath().toPortableString();
236 	}
237 
238 	/**
239 	 * Creates a fatal error status telling that the input element does not
240 	 * exist.
241 	 *
242 	 * @param element
243 	 *            the input element, or <code>null</code>
244 	 * @param name
245 	 *            the name of the refactoring
246 	 * @param id
247 	 *            the id of the refactoring
248 	 * @return the refactoring status
249 	 */
createInputFatalStatus(final Object element, final String name, final String id)250 	public static RefactoringStatus createInputFatalStatus(final Object element, final String name, final String id) {
251 		Assert.isNotNull(name);
252 		Assert.isNotNull(id);
253 		if (element != null)
254 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_input_not_exists, new String[] { JavaElementLabelsCore.getTextLabel(element, JavaElementLabelsCore.ALL_FULLY_QUALIFIED), name, id}));
255 		else
256 			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_inputs_do_not_exist, new String[] { name, id}));
257 	}
258 
259 	/**
260 	 * Creates a warning status telling that the input element does not exist.
261 	 *
262 	 * @param element
263 	 *            the input element, or <code>null</code>
264 	 * @param name
265 	 *            the name of the refactoring
266 	 * @param id
267 	 *            the id of the refactoring
268 	 * @return the refactoring status
269 	 */
createInputWarningStatus(final Object element, final String name, final String id)270 	public static RefactoringStatus createInputWarningStatus(final Object element, final String name, final String id) {
271 		Assert.isNotNull(name);
272 		Assert.isNotNull(id);
273 		if (element != null)
274 			return RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_input_not_exists, new String[] { JavaElementLabelsCore.getTextLabel(element, JavaElementLabelsCore.ALL_FULLY_QUALIFIED), name, id}));
275 		else
276 			return RefactoringStatus.createWarningStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_inputs_do_not_exist, new String[] { name, id}));
277 	}
278 
279 }
280