KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ltk > core > refactoring > RefactoringDescriptor


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.ltk.core.refactoring;
12
13 import org.eclipse.core.runtime.Assert;
14 import org.eclipse.core.runtime.CoreException;
15
16 import org.eclipse.ltk.core.refactoring.history.IRefactoringExecutionListener;
17 import org.eclipse.ltk.core.refactoring.history.IRefactoringHistoryListener;
18 import org.eclipse.ltk.core.refactoring.history.IRefactoringHistoryService;
19
20 /**
21  * Descriptor object of a refactoring.
22  * <p>
23  * A refactoring descriptor contains refactoring-specific data which allows the
24  * framework to completely reconstruct a particular refactoring instance and
25  * execute it on an arbitrary workspace.
26  * </p>
27  * <p>
28  * Refactoring descriptors contain the following information:
29  * <ul>
30  * <li>a short description string, which provides a human-readable text
31  * designed to be displayed in the user interface to represent the refactoring
32  * in trees and lists. Descriptions are automatically generated by refactorings.</li>
33  * <li> an optional comment string, which provides a full human-readable
34  * description of the refactoring. Comments are automatically generated by
35  * refactorings and provide more refactoring-specific information, such as which
36  * elements have participated in the refactoring. </li>
37  * <li> refactoring descriptor flags, which tell the framework what capabilities
38  * or properties a certain refactorings has when executed in a remote context.
39  * </li>
40  * <li> a timestamp, measured as the milliseconds since January 1, 1970,
41  * 00:00:00 GMT, which denotes the original execution time of the refactoring.
42  * </li>
43  * <li> a unique ID, which denotes a certain kind of refactoring (e.g. Rename
44  * File). This ID is usually composed of the plugin identifier of the
45  * contributing plugin and a plugin-wide unique identifier (e.g.
46  * <code>org.eclipse.ltk.core.refactoring.renameFile</code>). </li>
47  * <li> the optional name of the project this refactoring is associated with.
48  * Note that the project name is not available if the refactoring cannot be
49  * associated with a single project, or the refactoring descriptor has been read
50  * from a file which cannot be associated with a project. </li>
51  * </ul>
52  * </p>
53  * <p>
54  * Refactoring descriptors are identified by their refactoring id
55  * {@link #getID()} and their time stamps {@link #getTimeStamp()} and are
56  * potentially heavy weight objects which should not be held on to. Use
57  * refactoring descriptor proxies {@link RefactoringDescriptorProxy} to present
58  * refactoring descriptors in the user interface or otherwise manipulate
59  * refactoring histories.
60  * </p>
61  * <p>
62  * Clients which create specific refactoring descriptors during change
63  * generation should choose a short, informative and human-readable description
64  * of the particular refactoring instance and pass appropriate descriptor flags
65  * to the constructor. More details about a particular refactoring can be
66  * revealed in the comment, which contains more text with refactoring-specific
67  * information.
68  * </p>
69  * <p>
70  * Refactoring descriptors do not provide version information. It is the
71  * responsibility of the client to enhance subclasses with refactoring version
72  * information in order to provide a means of schema evolution.
73  * </p>
74  * <p>
75  * All time stamps are measured as the milliseconds since January 1, 1970,
76  * 00:00:00 GMT.
77  * </p>
78  * <p>
79  * Note: this class is indented to be subclassed by clients to provide
80  * specialized refactoring descriptors for particular refactorings.
81  * </p>
82  *
83  * @see RefactoringDescriptorProxy
84  * @see IRefactoringHistoryService
85  *
86  * @since 3.2
87  */

88 public abstract class RefactoringDescriptor implements Comparable JavaDoc {
89
90     /**
91      * Constant describing the API change flag (value: <code>1</code>).
92      * <p>
93      * Clients should set this flag to indicate that the represented refactoring
94      * may cause breaking API changes. If clients set the
95      * {@link #BREAKING_CHANGE} flag, they should set {@link #STRUCTURAL_CHANGE}
96      * as well. Typically, refactorings which change elements that are marked as
97      * API according to the semantics of the associated programming language
98      * should set this flag. This flag is used by the refactoring framework to
99      * determine whether a refactoring may break existing API when replayed by
100      * clients.
101      * </p>
102      */

103     public static final int BREAKING_CHANGE= 1 << 0;
104
105     /**
106      * The unknown refactoring id (value:
107      * <code>org.eclipse.ltk.core.refactoring.unknown</code>).
108      * <p>
109      * This id is reserved by the refactoring framework to signal that a
110      * refactoring has been performed which did not deliver a refactoring
111      * descriptor via its {@link Change#getDescriptor()} method. The refactoring
112      * history service never returns unknown refactorings. For consistency
113      * reasons, they are reported for {@link IRefactoringExecutionListener} or
114      * {@link IRefactoringHistoryListener} in order to keep clients of these
115      * listeners synchronized with the workbench's operation history.
116      * </p>
117      */

118     public static final String JavaDoc ID_UNKNOWN= "org.eclipse.ltk.core.refactoring.unknown"; //$NON-NLS-1$
119

120     /**
121      * Constant describing the multi change flag (value: <code>4</code>).
122      * <p>
123      * Clients should set this flag to indicate that the change created by the
124      * represented refactoring might causes changes in other files than the
125      * files of the input elements according to the semantics of the associated
126      * programming language. Typically, refactorings which update references to
127      * the refactored element should set this flag. This flag is used during
128      * team synchronize operations to optimize the processing of refactorings.
129      * </p>
130      */

131     public static final int MULTI_CHANGE= 1 << 2;
132
133     /** Constant describing the absence of any flags (value: <code>0</code>). */
134     public static final int NONE= 0;
135
136     /**
137      * Constant describing the structural change flag (value: <code>2</code>).
138      * <p>
139      * Clients should set this flag to indicate that the change created by the
140      * represented refactoring might be a structural change according to the
141      * semantics of the associated programming language. Typically, refactorings
142      * which cause changes in elements other than the element which declares the
143      * refactored element should set this flag. This flag is used by
144      * language-specific tools to determine whether the refactoring may impact
145      * client code.
146      * </p>
147      */

148     public static final int STRUCTURAL_CHANGE= 1 << 1;
149
150     /**
151      * Constant describing the user flag (value: <code>256</code>).
152      * <p>
153      * This constant is not intended to be used in refactoring descriptors.
154      * Clients should use the value of this constant to define user-defined
155      * flags with integer values greater than this constant. Clients must not
156      * use this constant directly.
157      * </p>
158      */

159     public static final int USER_CHANGE= 1 << 8;
160
161     /** The comment of the refactoring, or <code>null</code> for no comment */
162     private String JavaDoc fComment;
163
164     /** The non-empty description of the refactoring */
165     private String JavaDoc fDescription;
166
167     /** The flags of the refactoring, or <code>NONE</code> */
168     private int fFlags;
169
170     /** The project name, or <code>null</code> for no project */
171     private String JavaDoc fProject;
172
173     /** The unique id of the refactoring */
174     private final String JavaDoc fRefactoringId;
175
176     /**
177      * The time stamp, or <code>-1</code> if no time information is associated
178      * with the refactoring
179      */

180     private long fTimeStamp= -1;
181
182     /**
183      * Creates a new refactoring descriptor.
184      *
185      * @param id
186      * the unique id of the refactoring
187      * @param project
188      * the non-empty name of the project associated with this
189      * refactoring, or <code>null</code> for a workspace
190      * refactoring
191      * @param description
192      * a non-empty human-readable description of the particular
193      * refactoring instance
194      * @param comment
195      * the human-readable comment of the particular refactoring
196      * instance, or <code>null</code> for no comment
197      * @param flags
198      * the flags of the refactoring descriptor
199      */

200     protected RefactoringDescriptor(final String JavaDoc id, final String JavaDoc project, final String JavaDoc description, final String JavaDoc comment, final int flags) {
201         Assert.isNotNull(id);
202         Assert.isLegal(!"".equals(id), "Refactoring id must not be empty"); //$NON-NLS-1$ //$NON-NLS-2$
203
Assert.isLegal(project == null || !"".equals(project), "Project must either be null or non-empty"); //$NON-NLS-1$ //$NON-NLS-2$
204
Assert.isNotNull(description);
205         Assert.isLegal(!"".equals(description), "Description must not be empty"); //$NON-NLS-1$//$NON-NLS-2$
206
Assert.isLegal(flags >= NONE, "Flags must be non-negative"); //$NON-NLS-1$
207
fRefactoringId= id;
208         fDescription= description;
209         fProject= project;
210         fComment= comment;
211         fFlags= flags;
212     }
213
214     /**
215      * {@inheritDoc}
216      */

217     public final int compareTo(final Object JavaDoc object) {
218         if (object instanceof RefactoringDescriptor) {
219             final RefactoringDescriptor descriptor= (RefactoringDescriptor) object;
220             final long delta= fTimeStamp - descriptor.fTimeStamp;
221             if (delta < 0)
222                 return -1;
223             else if (delta > 0)
224                 return +1;
225         }
226         return 0;
227     }
228
229     /**
230      * Creates the a new refactoring instance for this refactoring descriptor.
231      * <p>
232      * This method is used by the refactoring framework to instantiate a
233      * refactoring from a refactoring descriptor, in order to apply it later on
234      * a local or remote workspace.
235      * </p>
236      * <p>
237      * The returned refactoring must be in an initialized state, i.e. ready to
238      * be executed via {@link PerformRefactoringOperation}.
239      * </p>
240      *
241      * @param status
242      * a refactoring status used to describe the outcome of the
243      * initialization
244      * @return the refactoring, or <code>null</code> if this refactoring
245      * descriptor represents the unknown refactoring, or if no
246      * refactoring contribution is available for this refactoring
247      * descriptor which is capable to create a refactoring
248      * @throws CoreException
249      * if an error occurs while creating the refactoring instance
250      */

251     public abstract Refactoring createRefactoring(RefactoringStatus status) throws CoreException;
252
253     /**
254      * {@inheritDoc}
255      */

256     public final boolean equals(final Object JavaDoc object) {
257         if (object instanceof RefactoringDescriptor) {
258             final RefactoringDescriptor descriptor= (RefactoringDescriptor) object;
259             return fTimeStamp == descriptor.fTimeStamp && getDescription().equals(descriptor.getDescription());
260         }
261         return false;
262     }
263
264     /**
265      * Returns the details comment.
266      * <p>
267      * This information is used in the user interface to show additional details
268      * about the performed refactoring.
269      * </p>
270      *
271      * @return the details comment, or the empty string
272      */

273     public final String JavaDoc getComment() {
274         return (fComment != null) ? fComment : ""; //$NON-NLS-1$
275
}
276
277     /**
278      * Returns the description.
279      * <p>
280      * This information is used to label a refactoring in the user interface.
281      * </p>
282      *
283      * @return the description
284      */

285     public final String JavaDoc getDescription() {
286         return fDescription;
287     }
288
289     /**
290      * Returns the flags.
291      *
292      * @return the flags
293      */

294     public final int getFlags() {
295         return fFlags;
296     }
297
298     /**
299      * Returns the refactoring id.
300      *
301      * @return the refactoring id.
302      */

303     public final String JavaDoc getID() {
304         return fRefactoringId;
305     }
306
307     /**
308      * Returns the project name.
309      *
310      * @return the non-empty name of the project, or <code>null</code>
311      */

312     public final String JavaDoc getProject() {
313         return fProject;
314     }
315
316     /**
317      * Returns the time stamp.
318      *
319      * @return the time stamp, or <code>-1</code> if no time information is
320      * available
321      */

322     public final long getTimeStamp() {
323         return fTimeStamp;
324     }
325
326     /**
327      * {@inheritDoc}
328      */

329     public final int hashCode() {
330         int code= getDescription().hashCode();
331         if (fTimeStamp >= 0)
332             code+= (17 * fTimeStamp);
333         return code;
334     }
335
336     /**
337      * Sets the details comment of this refactoring.
338      * <p>
339      * Note: This API must not be extended or reimplemented and should not be
340      * called from outside the refactoring framework.
341      * </p>
342      *
343      * @param comment
344      * the comment to set, or <code>null</code> for no comment
345      */

346     public void setComment(final String JavaDoc comment) {
347         fComment= comment;
348     }
349
350     /**
351      * Sets the description of this refactoring.
352      * <p>
353      * Note: This API must not be extended or reimplemented and should not be
354      * called from outside the refactoring framework.
355      * </p>
356      *
357      * @param description
358      * the non-empty description of the refactoring to set
359      *
360      * @since 3.3
361      */

362     public void setDescription(final String JavaDoc description) {
363         Assert.isNotNull(description);
364         Assert.isLegal(!"".equals(description), "Description must not be empty"); //$NON-NLS-1$ //$NON-NLS-2$
365
fDescription= description;
366     }
367
368     /**
369      * Sets the flags of this refactoring.
370      * <p>
371      * Note: This API must not be extended or reimplemented and should not be
372      * called from outside the refactoring framework.
373      * </p>
374      *
375      * @param flags
376      * the flags to set, or <code>NONE</code> to clear the flags
377      *
378      * @since 3.3
379      */

380     public void setFlags(final int flags) {
381         Assert.isLegal(flags >= NONE, "Flags must be non-negative"); //$NON-NLS-1$
382
fFlags= flags;
383     }
384
385     /**
386      * Sets the project name of this refactoring.
387      * <p>
388      * Note: This API must not be extended or reimplemented and should not be
389      * called from outside the refactoring framework.
390      * </p>
391      *
392      * @param project
393      * the non-empty project name to set, or <code>null</code> for
394      * the workspace
395      */

396     public void setProject(final String JavaDoc project) {
397         Assert.isLegal(project == null || !"".equals(project), "Project must either be null or non-empty"); //$NON-NLS-1$ //$NON-NLS-2$
398
fProject= project;
399     }
400
401     /**
402      * Sets the time stamp of this refactoring. This method can be called only
403      * once.
404      * <p>
405      * Note: This API must not be extended or reimplemented and should not be
406      * called from outside the refactoring framework.
407      * </p>
408      *
409      * @param stamp
410      * the time stamp to set
411      */

412     public void setTimeStamp(final long stamp) {
413         Assert.isTrue(stamp >= 0);
414         fTimeStamp= stamp;
415     }
416
417     /**
418      * {@inheritDoc}
419      */

420     public String JavaDoc toString() {
421
422         final StringBuffer JavaDoc buffer= new StringBuffer JavaDoc(128);
423
424         buffer.append(getClass().getName());
425         if (fRefactoringId.equals(ID_UNKNOWN))
426             buffer.append("[unknown refactoring]"); //$NON-NLS-1$
427
else {
428             buffer.append("[timeStamp="); //$NON-NLS-1$
429
buffer.append(fTimeStamp);
430             buffer.append(",id="); //$NON-NLS-1$
431
buffer.append(fRefactoringId);
432             buffer.append(",description="); //$NON-NLS-1$
433
buffer.append(fDescription);
434             buffer.append(",project="); //$NON-NLS-1$
435
buffer.append(fProject);
436             buffer.append(",comment="); //$NON-NLS-1$
437
buffer.append(fComment);
438             buffer.append(",flags="); //$NON-NLS-1$
439
buffer.append(fFlags);
440             buffer.append("]"); //$NON-NLS-1$
441
}
442
443         return buffer.toString();
444     }
445 }
446
Popular Tags