KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > nls > NLSRefactoring


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.refactoring.nls;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.runtime.Assert;
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.OperationCanceledException;
21 import org.eclipse.core.runtime.SubProgressMonitor;
22
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IResource;
25 import org.eclipse.core.resources.ResourcesPlugin;
26
27 import org.eclipse.ltk.core.refactoring.Change;
28 import org.eclipse.ltk.core.refactoring.Refactoring;
29 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
30 import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
31 import org.eclipse.osgi.util.NLS;
32
33 import org.eclipse.jdt.core.ICompilationUnit;
34 import org.eclipse.jdt.core.IPackageFragment;
35 import org.eclipse.jdt.core.IType;
36 import org.eclipse.jdt.core.JavaModelException;
37 import org.eclipse.jdt.core.dom.CompilationUnit;
38
39 import org.eclipse.jdt.internal.corext.SourceRange;
40 import org.eclipse.jdt.internal.corext.refactoring.Checks;
41 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
42 import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
43 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
44 import org.eclipse.jdt.internal.corext.util.Messages;
45
46 import org.eclipse.jdt.internal.ui.JavaPlugin;
47 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
48
49 public class NLSRefactoring extends Refactoring {
50
51     public static final String JavaDoc BUNDLE_NAME= "BUNDLE_NAME"; //$NON-NLS-1$
52
public static final String JavaDoc PROPERTY_FILE_EXT= ".properties"; //$NON-NLS-1$
53
public static final String JavaDoc DEFAULT_ACCESSOR_CLASSNAME= "Messages"; //$NON-NLS-1$
54

55     public static final String JavaDoc KEY= "${key}"; //$NON-NLS-1$
56
public static final String JavaDoc DEFAULT_SUBST_PATTERN= "getString(" + KEY + ")"; //$NON-NLS-1$ //$NON-NLS-2$
57

58     public static final String JavaDoc DEFAULT_PROPERTY_FILENAME= "messages"; //$NON-NLS-1$
59

60     //private IPath fPropertyFilePath;
61

62     private String JavaDoc fAccessorClassName;
63     private IPackageFragment fAccessorClassPackage;
64     private String JavaDoc fResourceBundleName;
65     private IPackageFragment fResourceBundlePackage;
66
67     private String JavaDoc fSubstitutionPattern;
68     private ICompilationUnit fCu;
69     private NLSSubstitution[] fSubstitutions;
70     
71     private String JavaDoc fPrefix;
72     
73     /**
74      * <code>true</code> if the standard resource bundle mechanism
75      * is used and <code>false</code> NLSing is done the Eclipse way.
76      */

77     private boolean fIsEclipseNLS;
78
79     private NLSRefactoring(ICompilationUnit cu) {
80         Assert.isNotNull(cu);
81         fCu= cu;
82
83         CompilationUnit astRoot= JavaPlugin.getDefault().getASTProvider().getAST(fCu, ASTProvider.WAIT_YES, null);
84         NLSHint nlsHint= new NLSHint(fCu, astRoot);
85
86         fSubstitutions= nlsHint.getSubstitutions();
87         setAccessorClassName(nlsHint.getAccessorClassName());
88         setAccessorClassPackage(nlsHint.getAccessorClassPackage());
89         setIsEclipseNLS(detectIsEclipseNLS());
90         setResourceBundleName(nlsHint.getResourceBundleName());
91         setResourceBundlePackage(nlsHint.getResourceBundlePackage());
92         setSubstitutionPattern(DEFAULT_SUBST_PATTERN);
93         
94         String JavaDoc cuName= fCu.getElementName();
95         if (fIsEclipseNLS)
96             setPrefix(cuName.substring(0, cuName.length() - 5) + "_"); // A.java -> A_ //$NON-NLS-1$
97
else
98             setPrefix(cuName.substring(0, cuName.length() - 4)); // A.java -> A.
99
}
100
101     public static NLSRefactoring create(ICompilationUnit cu) {
102         if (cu == null || !cu.exists())
103             return null;
104         return new NLSRefactoring(cu);
105     }
106
107     /**
108      * no validation is done
109      *
110      * @param pattern
111      * Example: "Messages.getString(${key})". Must not be
112      * <code>null</code>. should (but does not have to) contain
113      * NLSRefactoring.KEY (default value is $key$) only the first
114      * occurrence of this key will be used
115      */

116     public void setSubstitutionPattern(String JavaDoc pattern) {
117         Assert.isNotNull(pattern);
118         fSubstitutionPattern= pattern;
119     }
120
121     /**
122      * to show the pattern in the UI
123      */

124     public String JavaDoc getSubstitutionPattern() {
125         if (fIsEclipseNLS)
126             return KEY;
127         else
128             return fSubstitutionPattern;
129     }
130
131     public ICompilationUnit getCu() {
132         return fCu;
133     }
134
135     public String JavaDoc getName() {
136         return Messages.format(NLSMessages.NLSRefactoring_compilation_unit, fCu.getElementName());
137     }
138
139     public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
140
141         if (fSubstitutions.length == 0) {
142             String JavaDoc message= Messages.format(NLSMessages.NLSRefactoring_no_strings, fCu.getElementName());
143             return RefactoringStatus.createFatalErrorStatus(message);
144         }
145         return new RefactoringStatus();
146     }
147
148     public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
149         checkParameters();
150         try {
151
152             pm.beginTask(NLSMessages.NLSRefactoring_checking, 5);
153
154             RefactoringStatus result= new RefactoringStatus();
155
156             result.merge(checkIfAnythingToDo());
157             if (result.hasFatalError()) {
158                 return result;
159             }
160             pm.worked(1);
161
162             result.merge(validateModifiesFiles());
163             if (result.hasFatalError()) {
164                 return result;
165             }
166             pm.worked(1);
167             if (pm.isCanceled())
168                 throw new OperationCanceledException();
169
170             result.merge(checkSubstitutionPattern());
171             pm.worked(1);
172
173             if (pm.isCanceled())
174                 throw new OperationCanceledException();
175
176
177             result.merge(checkKeys());
178             pm.worked(1);
179             if (pm.isCanceled())
180                 throw new OperationCanceledException();
181
182             if (!propertyFileExists() && willModifyPropertyFile()) {
183                 String JavaDoc msg= Messages.format(NLSMessages.NLSRefactoring_will_be_created, getPropertyFilePath().toString());
184                 result.addInfo(msg);
185             }
186             pm.worked(1);
187
188             return result;
189         } finally {
190             pm.done();
191         }
192     }
193
194     public Change createChange(IProgressMonitor pm) throws CoreException {
195         try {
196             checkParameters();
197
198             pm.beginTask("", 3); //$NON-NLS-1$
199

200             final DynamicValidationStateChange result= new DynamicValidationStateChange(NLSMessages.NLSRefactoring_change_name);
201
202             boolean createAccessorClass= willCreateAccessorClass();
203             if (NLSSubstitution.countItems(fSubstitutions, NLSSubstitution.EXTERNALIZED) == 0) {
204                 createAccessorClass= false;
205             }
206             if (createAccessorClass) {
207                 result.add(AccessorClassCreator.create(fCu, fAccessorClassName, getAccessorCUPath(), fAccessorClassPackage, getPropertyFilePath(), fIsEclipseNLS, fSubstitutions, getSubstitutionPattern(), new SubProgressMonitor(pm, 1)));
208             }
209             pm.worked(1);
210
211             if (willModifySource()) {
212                 result.add(NLSSourceModifier.create(getCu(), fSubstitutions, getSubstitutionPattern(), fAccessorClassPackage, fAccessorClassName, fIsEclipseNLS));
213             }
214             pm.worked(1);
215
216             if (willModifyPropertyFile()) {
217                 result.add(NLSPropertyFileModifier.create(fSubstitutions, getPropertyFilePath()));
218                 if (isEclipseNLS() && !createAccessorClass) {
219                     Change change= AccessorClassModifier.create(getAccessorCu(), fSubstitutions);
220                     if (change != null)
221                         result.add(change);
222                 }
223             }
224             pm.worked(1);
225
226             return result;
227         } finally {
228             pm.done();
229         }
230     }
231
232     private void checkParameters() {
233         Assert.isNotNull(fSubstitutions);
234         Assert.isNotNull(fAccessorClassPackage);
235
236         // these values have defaults ...
237
Assert.isNotNull(fAccessorClassName);
238         Assert.isNotNull(getSubstitutionPattern());
239     }
240
241     private IFile[] getAllFilesToModify() {
242
243         List JavaDoc files= new ArrayList JavaDoc(2);
244         if (willModifySource()) {
245             IResource resource= fCu.getResource();
246             if (resource.exists()) {
247                 files.add(resource);
248             }
249         }
250
251         if (willModifyPropertyFile()) {
252             IFile file= getPropertyFileHandle();
253             if (file.exists()) {
254                 files.add(file);
255             }
256         }
257         
258         if (willModifyAccessorClass()) {
259             IFile file= getAccessorClassFileHandle();
260             if (file.exists()) {
261                 files.add(file);
262             }
263         }
264         
265         return (IFile[]) files.toArray(new IFile[files.size()]);
266     }
267
268     public IFile getPropertyFileHandle() {
269         return ResourcesPlugin.getWorkspace().getRoot().getFile(getPropertyFilePath());
270     }
271
272     public IPath getPropertyFilePath() {
273         return fResourceBundlePackage.getPath().append(fResourceBundleName);
274     }
275     
276     public IFile getAccessorClassFileHandle() {
277         return ResourcesPlugin.getWorkspace().getRoot().getFile(getAccessorClassFilePath());
278     }
279     
280     public IPath getAccessorClassFilePath() {
281         return getAccessorCUPath();
282     }
283
284     private RefactoringStatus validateModifiesFiles() {
285         return Checks.validateModifiesFiles(getAllFilesToModify(), getValidationContext());
286     }
287
288     //should stop checking if fatal error
289
private RefactoringStatus checkIfAnythingToDo() throws JavaModelException {
290         if (NLSSubstitution.countItems(fSubstitutions, NLSSubstitution.EXTERNALIZED) != 0 && willCreateAccessorClass())
291             return null;
292
293         if (willModifyPropertyFile())
294             return null;
295
296         if (willModifySource())
297             return null;
298
299         RefactoringStatus result= new RefactoringStatus();
300         result.addFatalError(NLSMessages.NLSRefactoring_nothing_to_do);
301         return result;
302     }
303
304     private boolean propertyFileExists() {
305         return getPropertyFileHandle().exists();
306     }
307
308     private RefactoringStatus checkSubstitutionPattern() {
309         String JavaDoc pattern= getSubstitutionPattern();
310
311         RefactoringStatus result= new RefactoringStatus();
312         if (pattern.trim().length() == 0) {//
313
result.addError(NLSMessages.NLSRefactoring_pattern_empty);
314         }
315
316         if (pattern.indexOf(KEY) == -1) {
317             String JavaDoc msg= Messages.format(NLSMessages.NLSRefactoring_pattern_does_not_contain, KEY);
318             result.addWarning(msg);
319         }
320
321         if (pattern.indexOf(KEY) != pattern.lastIndexOf(KEY)) {
322             String JavaDoc msg= Messages.format(NLSMessages.NLSRefactoring_Only_the_first_occurrence_of, KEY);
323             result.addWarning(msg);
324         }
325
326         return result;
327     }
328
329     private RefactoringStatus checkKeys() {
330         RefactoringStatus result= new RefactoringStatus();
331         NLSSubstitution[] subs= fSubstitutions;
332         for (int i= 0; i < subs.length; i++) {
333             NLSSubstitution substitution= subs[i];
334             if ((substitution.getState() == NLSSubstitution.EXTERNALIZED) && substitution.hasStateChanged()) {
335                 result.merge(checkKey(substitution.getKey()));
336             }
337         }
338         return result;
339     }
340
341     private static RefactoringStatus checkKey(String JavaDoc key) {
342         RefactoringStatus result= new RefactoringStatus();
343
344         if (key == null)
345             result.addFatalError(NLSMessages.NLSRefactoring_null);
346
347         if (key.startsWith("!") || key.startsWith("#")) { //$NON-NLS-1$ //$NON-NLS-2$
348
RefactoringStatusContext context= new JavaStringStatusContext(key, new SourceRange(0, 0));
349             result.addWarning(NLSMessages.NLSRefactoring_warning, context);
350         }
351
352         if ("".equals(key.trim())) //$NON-NLS-1$
353
result.addFatalError(NLSMessages.NLSRefactoring_empty);
354
355         final String JavaDoc[] UNWANTED_STRINGS= {" ", ":", "\"", "\\", "'", "?", "="}; //$NON-NLS-7$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
356
//feature in resource bundle - does not work properly if keys have ":"
357
for (int i= 0; i < UNWANTED_STRINGS.length; i++) {
358             if (key.indexOf(UNWANTED_STRINGS[i]) != -1) {
359                 String JavaDoc[] args= {key, UNWANTED_STRINGS[i]};
360                 String JavaDoc msg= Messages.format(NLSMessages.NLSRefactoring_should_not_contain, args);
361                 result.addError(msg);
362             }
363         }
364         return result;
365     }
366
367     public boolean willCreateAccessorClass() throws JavaModelException {
368
369         ICompilationUnit compilationUnit= getAccessorCu();
370         if (compilationUnit.exists()) {
371             return false;
372         }
373
374         if (typeNameExistsInPackage(fAccessorClassPackage, fAccessorClassName)) {
375             return false;
376         }
377
378         return (!Checks.resourceExists(getAccessorCUPath()));
379     }
380
381     private ICompilationUnit getAccessorCu() {
382         return fAccessorClassPackage.getCompilationUnit(getAccessorCUName());
383     }
384
385     private boolean willModifySource() {
386         NLSSubstitution[] subs= fSubstitutions;
387         for (int i= 0; i < subs.length; i++) {
388             if (subs[i].hasSourceChange())
389                 return true;
390         }
391         return false;
392     }
393
394     private boolean willModifyPropertyFile() {
395         NLSSubstitution[] subs= fSubstitutions;
396         for (int i= 0; i < subs.length; i++) {
397             NLSSubstitution substitution= subs[i];
398             if (substitution.hasPropertyFileChange()) {
399                 return true;
400             }
401         }
402         return false;
403     }
404     
405     private boolean willModifyAccessorClass() {
406         if (!isEclipseNLS())
407             return false;
408
409         NLSSubstitution[] subs= fSubstitutions;
410         for (int i= 0; i < subs.length; i++) {
411             NLSSubstitution substitution= subs[i];
412             if (substitution.hasAccessorClassChange()) {
413                 return true;
414             }
415         }
416         return false;
417     }
418
419     private boolean typeNameExistsInPackage(IPackageFragment pack, String JavaDoc name) throws JavaModelException {
420         return Checks.findTypeInPackage(pack, name) != null;
421     }
422
423     private String JavaDoc getAccessorCUName() {
424         return getAccessorClassName() + JavaModelUtil.DEFAULT_CU_SUFFIX;
425     }
426
427     private IPath getAccessorCUPath() {
428         return fAccessorClassPackage.getPath().append(getAccessorCUName());
429     }
430
431     public NLSSubstitution[] getSubstitutions() {
432         return fSubstitutions;
433     }
434
435     public String JavaDoc getPrefix() {
436         return fPrefix;
437     }
438     
439     public void setPrefix(String JavaDoc prefix) {
440         fPrefix= prefix;
441         if (fSubstitutions != null) {
442             for (int i= 0; i < fSubstitutions.length; i++)
443                 fSubstitutions[i].setPrefix(prefix);
444         }
445     }
446
447     public void setAccessorClassName(String JavaDoc name) {
448         Assert.isNotNull(name);
449         fAccessorClassName= name;
450     }
451
452     public void setAccessorClassPackage(IPackageFragment packageFragment) {
453         Assert.isNotNull(packageFragment);
454         fAccessorClassPackage= packageFragment;
455     }
456     
457     /**
458      * Sets whether the Eclipse NLSing mechanism or
459      * standard resource bundle mechanism is used.
460      *
461      * @param isEclipseNLS <code>true</code> if NLSing is done the Eclipse way
462      * and <code>false</code> if the standard resource bundle mechanism is used
463      * @since 3.1
464      */

465     public void setIsEclipseNLS(boolean isEclipseNLS) {
466         fIsEclipseNLS= isEclipseNLS;
467     }
468
469     public void setResourceBundlePackage(IPackageFragment resourceBundlePackage) {
470         Assert.isNotNull(resourceBundlePackage);
471         fResourceBundlePackage= resourceBundlePackage;
472     }
473
474     public void setResourceBundleName(String JavaDoc resourceBundleName) {
475         Assert.isNotNull(resourceBundleName);
476         fResourceBundleName= resourceBundleName;
477     }
478
479     public IPackageFragment getAccessorClassPackage() {
480         return fAccessorClassPackage;
481     }
482     
483     /**
484      * Computes whether the Eclipse NLSing mechanism is used.
485      *
486      * @return <code>true</code> if NLSing is done the Eclipse way
487      * and <code>false</code> if the standard resource bundle mechanism is used
488      * @since 3.1
489      */

490     public boolean detectIsEclipseNLS() {
491         if (getAccessorClassPackage() != null) {
492             ICompilationUnit accessorCU= getAccessorClassPackage().getCompilationUnit(getAccessorCUName());
493             IType type= accessorCU.getType(getAccessorClassName());
494             if (type.exists()) {
495                 try {
496                     String JavaDoc superclassName= type.getSuperclassName();
497                     if (!"NLS".equals(superclassName) && !NLS.class.getName().equals(superclassName)) //$NON-NLS-1$
498
return false;
499                     IType superclass= type.newSupertypeHierarchy(null).getSuperclass(type);
500                     return superclass != null && NLS.class.getName().equals(superclass.getFullyQualifiedName());
501                 } catch (JavaModelException e) {
502                     return false;
503                 }
504             }
505         }
506         return fIsEclipseNLS;
507     }
508     
509     /**
510      * Returns whether the Eclipse NLSing mechanism or
511      * the standard resource bundle mechanism is used.
512      *
513      * @return <code>true</code> if NLSing is done the Eclipse way
514      * and <code>false</code> if the standard resource bundle mechanism is used
515      * @since 3.1
516      */

517     public boolean isEclipseNLS() {
518         return fIsEclipseNLS;
519     }
520
521     public IPackageFragment getResourceBundlePackage() {
522         return fResourceBundlePackage;
523     }
524
525     public String JavaDoc getAccessorClassName() {
526         return fAccessorClassName;
527     }
528
529     public String JavaDoc getResourceBundleName() {
530         return fResourceBundleName;
531     }
532 }
533
Popular Tags