]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/nls/NLSRefactoring.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / nls / NLSRefactoring.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2011 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 * Eric Rizzo - Externalize Strings wizard always defaults to the "legacy" mechanism - http://bugs.eclipse.org/271375
11 *******************************************************************************/
12package org.eclipse.jdt.internal.corext.refactoring.nls;
13
14import java.util.ArrayList;
15import java.util.List;
16
17import org.eclipse.osgi.util.NLS;
18
19import org.eclipse.swt.events.ModifyEvent;
20import org.eclipse.swt.events.ModifyListener;
21
22import org.eclipse.core.runtime.Assert;
23import org.eclipse.core.runtime.CoreException;
24import org.eclipse.core.runtime.IPath;
25import org.eclipse.core.runtime.IProgressMonitor;
26import org.eclipse.core.runtime.OperationCanceledException;
27
28import org.eclipse.core.resources.IFile;
29import org.eclipse.core.resources.IResource;
30import org.eclipse.core.resources.ResourcesPlugin;
31
32import org.eclipse.jface.window.Window;
33
34import org.eclipse.ltk.core.refactoring.Change;
35import org.eclipse.ltk.core.refactoring.Refactoring;
36import org.eclipse.ltk.core.refactoring.RefactoringStatus;
37import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
38
39import org.eclipse.jdt.core.ICompilationUnit;
40import org.eclipse.jdt.core.IJavaProject;
41import org.eclipse.jdt.core.IPackageFragment;
42import org.eclipse.jdt.core.IType;
43import org.eclipse.jdt.core.JavaModelException;
44import org.eclipse.jdt.core.SourceRange;
45import org.eclipse.jdt.core.dom.CompilationUnit;
46
47import org.eclipse.jdt.internal.corext.refactoring.Checks;
48import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
49import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationStateChange;
50import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
51import org.eclipse.jdt.internal.corext.util.Messages;
52
53import org.eclipse.jdt.ui.SharedASTProvider;
54
55import org.eclipse.jdt.internal.ui.refactoring.nls.AccessorDescription;
56import org.eclipse.jdt.internal.ui.refactoring.nls.ExternalizeWizardPage;
57import org.eclipse.jdt.internal.ui.refactoring.nls.NLSAccessorConfigurationDialog;
58import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
59
60
61public class NLSRefactoring extends Refactoring {
62
63 public static final String BUNDLE_NAME_FIELD= "BUNDLE_NAME"; //$NON-NLS-1$
64 public static final String PROPERTY_FILE_EXT= ".properties"; //$NON-NLS-1$
65 public static final String DEFAULT_ACCESSOR_CLASSNAME= "Messages"; //$NON-NLS-1$
66
67 public static final String KEY= "${key}"; //$NON-NLS-1$
68 public static final String DEFAULT_SUBST_PATTERN= "getString(" + KEY + ")"; //$NON-NLS-1$ //$NON-NLS-2$
69
70 public static final String DEFAULT_PROPERTY_FILENAME= "messages"; //$NON-NLS-1$
71
72 //private IPath fPropertyFilePath;
73
74 public String fAccessorClassName;
75 public IPackageFragment fAccessorClassPackage;
76 private String fResourceBundleName;
77 private IPackageFragment fResourceBundlePackage;
78
79 private String fSubstitutionPattern;
80 public ICompilationUnit fCu;
81 public NLSSubstitution[] fSubstitutions;
82
83 private String fPrefix;
84
85 /**
86 * <code>true</code> if the standard resource bundle mechanism
87 * is used and <code>false</code> NLSing is done the Eclipse way.
88 */
89 public boolean fIsEclipseNLS;
90
91 private NLSRefactoring(ICompilationUnit cu) {
92 Assert.isNotNull(cu);
93 fCu= cu;
94
95 CompilationUnit astRoot= SharedASTProvider.getAST(fCu, SharedASTProvider.WAIT_YES, null);
96 NLSHint nlsHint= new NLSHint(fCu, astRoot);
97
98 fSubstitutions= nlsHint.getSubstitutions();
99 nlsHint.generated_9095855277300400094(this);
100 setSubstitutionPattern(DEFAULT_SUBST_PATTERN);
101
102 String cuName= fCu.getElementName();
103 if (fIsEclipseNLS)
104 setPrefix(cuName.substring(0, cuName.length() - 5) + "_"); // A.java -> A_ //$NON-NLS-1$
105 else
106 setPrefix(cuName.substring(0, cuName.length() - 4)); // A.java -> A.
107 }
108
109 public static NLSRefactoring create(ICompilationUnit cu) {
110 if (cu == null || !cu.exists())
111 return null;
112 return new NLSRefactoring(cu);
113 }
114
115 public boolean isEclipseNLSAvailable() {
116 if (getCu() == null)
117 return false;
118
119 IJavaProject javaProject= getCu().getJavaProject();
120 if (javaProject == null || !javaProject.exists())
121 return false;
122
123 try {
124 return javaProject.findType("org.eclipse.osgi.util.NLS") != null; //$NON-NLS-1$
125 } catch (JavaModelException e) {
126 return false;
127 }
128 }
129
130
131 /**
132 * no validation is done
133 *
134 * @param pattern
135 * Example: "Messages.getString(${key})". Must not be
136 * <code>null</code>. should (but does not have to) contain
137 * NLSRefactoring.KEY (default value is $key$) only the first
138 * occurrence of this key will be used
139 */
140 public void setSubstitutionPattern(String pattern) {
141 Assert.isNotNull(pattern);
142 fSubstitutionPattern= pattern;
143 }
144
145 /**
146 * to show the pattern in the UI
147 * @return the substitution pattern
148 */
149 public String getSubstitutionPattern() {
150 if (fIsEclipseNLS)
151 return KEY;
152 else
153 return fSubstitutionPattern;
154 }
155
156 public ICompilationUnit getCu() {
157 return fCu;
158 }
159
160 @Override
161 public String getName() {
162 return Messages.format(NLSMessages.NLSRefactoring_compilation_unit, BasicElementLabels.getFileName(fCu));
163 }
164
165 @Override
166 public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
167
168 if (fSubstitutions.length == 0) {
169 String message= Messages.format(NLSMessages.NLSRefactoring_no_strings, BasicElementLabels.getFileName(fCu));
170 return RefactoringStatus.createFatalErrorStatus(message);
171 }
172 return new RefactoringStatus();
173 }
174
175 @Override
176 public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
177 checkParameters();
178 try {
179
180 pm.beginTask(NLSMessages.NLSRefactoring_checking, 5);
181
182 RefactoringStatus result= new RefactoringStatus();
183
184 result.merge(checkIfAnythingToDo());
185 if (result.hasFatalError()) {
186 return result;
187 }
188 pm.worked(1);
189
190 result.merge(validateModifiesFiles());
191 if (result.hasFatalError()) {
192 return result;
193 }
194 pm.worked(1);
195 if (pm.isCanceled())
196 throw new OperationCanceledException();
197
198 result.merge(checkSubstitutionPattern());
199 pm.worked(1);
200
201 if (pm.isCanceled())
202 throw new OperationCanceledException();
203
204
205 result.merge(checkKeys());
206 pm.worked(1);
207 if (pm.isCanceled())
208 throw new OperationCanceledException();
209
210 if (!propertyFileExists() && willModifyPropertyFile()) {
211 String msg= Messages.format(NLSMessages.NLSRefactoring_will_be_created, BasicElementLabels.getPathLabel(getPropertyFilePath(), false));
212 result.addInfo(msg);
213 }
214 pm.worked(1);
215
216 return result;
217 } finally {
218 pm.done();
219 }
220 }
221
222 @Override
223 public Change createChange(IProgressMonitor pm) throws CoreException {
224 try {
225 checkParameters();
226
227 pm.beginTask("", 3); //$NON-NLS-1$
228
229 final DynamicValidationStateChange result= new DynamicValidationStateChange(NLSMessages.NLSRefactoring_change_name);
230
231 boolean createAccessorClass= willCreateAccessorClass();
232 return result.generated_3017607861345422425(pm, this, createAccessorClass);
233 } finally {
234 pm.done();
235 }
236 }
237
238 private void checkParameters() {
239 Assert.isNotNull(fSubstitutions);
240 Assert.isNotNull(fAccessorClassPackage);
241
242 // these values have defaults ...
243 Assert.isNotNull(fAccessorClassName);
244 Assert.isNotNull(getSubstitutionPattern());
245 }
246
247 private IFile[] getAllFilesToModify() {
248
249 List<IResource> files= new ArrayList<IResource>(2);
250 if (willModifySource()) {
251 IResource resource= fCu.getResource();
252 if (resource.exists()) {
253 files.add(resource);
254 }
255 }
256
257 if (willModifyPropertyFile()) {
258 IFile file= getPropertyFileHandle();
259 if (file.exists()) {
260 files.add(file);
261 }
262 }
263
264 if (willModifyAccessorClass()) {
265 IFile file= getAccessorClassFileHandle();
266 if (file.exists()) {
267 files.add(file);
268 }
269 }
270
271 return files.toArray(new IFile[files.size()]);
272 }
273
274 public IFile getPropertyFileHandle() {
275 return ResourcesPlugin.getWorkspace().getRoot().getFile(getPropertyFilePath());
276 }
277
278 public IPath getPropertyFilePath() {
279 return fResourceBundlePackage.getPath().append(fResourceBundleName);
280 }
281
282 public IFile getAccessorClassFileHandle() {
283 return ResourcesPlugin.getWorkspace().getRoot().getFile(getAccessorClassFilePath());
284 }
285
286 public IPath getAccessorClassFilePath() {
287 return getAccessorCUPath();
288 }
289
290 private RefactoringStatus validateModifiesFiles() {
291 return Checks.validateModifiesFiles(getAllFilesToModify(), getValidationContext());
292 }
293
294 //should stop checking if fatal error
295 private RefactoringStatus checkIfAnythingToDo() throws JavaModelException {
296 if (NLSSubstitution.countItems(fSubstitutions, NLSSubstitution.EXTERNALIZED) != 0 && willCreateAccessorClass())
297 return null;
298
299 if (willModifyPropertyFile())
300 return null;
301
302 if (willModifySource())
303 return null;
304
305 RefactoringStatus result= new RefactoringStatus();
306 result.addFatalError(NLSMessages.NLSRefactoring_nothing_to_do);
307 return result;
308 }
309
310 private boolean propertyFileExists() {
311 return getPropertyFileHandle().exists();
312 }
313
314 private RefactoringStatus checkSubstitutionPattern() {
315 String pattern= getSubstitutionPattern();
316
317 RefactoringStatus result= new RefactoringStatus();
318 if (pattern.trim().length() == 0) {//
319 result.addError(NLSMessages.NLSRefactoring_pattern_empty);
320 }
321
322 if (pattern.indexOf(KEY) == -1) {
323 String msg= Messages.format(NLSMessages.NLSRefactoring_pattern_does_not_contain, KEY);
324 result.addWarning(msg);
325 }
326
327 if (pattern.indexOf(KEY) != pattern.lastIndexOf(KEY)) {
328 String msg= Messages.format(NLSMessages.NLSRefactoring_Only_the_first_occurrence_of, KEY);
329 result.addWarning(msg);
330 }
331
332 return result;
333 }
334
335 private RefactoringStatus checkKeys() {
336 RefactoringStatus result= new RefactoringStatus();
337 NLSSubstitution[] subs= fSubstitutions;
338 for (int i= 0; i < subs.length; i++) {
339 NLSSubstitution substitution= subs[i];
340 substitution.generated_192464520680034722(result);
341 }
342 return result;
343 }
344
345 static RefactoringStatus checkKey(String key) {
346 RefactoringStatus result= new RefactoringStatus();
347
348 if (key == null)
349 result.addFatalError(NLSMessages.NLSRefactoring_null);
350
351 if (key.startsWith("!") || key.startsWith("#")) { //$NON-NLS-1$ //$NON-NLS-2$
352 RefactoringStatusContext context= new JavaStringStatusContext(key, new SourceRange(0, 0));
353 result.addWarning(NLSMessages.NLSRefactoring_warning, context);
354 }
355
356 if ("".equals(key.trim())) //$NON-NLS-1$
357 result.addFatalError(NLSMessages.NLSRefactoring_empty);
358
359 final String[] UNWANTED_STRINGS= {" ", ":", "\"", "\\", "'", "?", "="}; //$NON-NLS-7$ //$NON-NLS-6$ //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$
360 //feature in resource bundle - does not work properly if keys have ":"
361 for (int i= 0; i < UNWANTED_STRINGS.length; i++) {
362 if (key.indexOf(UNWANTED_STRINGS[i]) != -1) {
363 String[] args= {key, UNWANTED_STRINGS[i]};
364 String msg= Messages.format(NLSMessages.NLSRefactoring_should_not_contain, args);
365 result.addError(msg);
366 }
367 }
368 return result;
369 }
370
371 public boolean willCreateAccessorClass() throws JavaModelException {
372
373 ICompilationUnit compilationUnit= getAccessorCu();
374 if (compilationUnit.exists()) {
375 return false;
376 }
377
378 if (typeNameExistsInPackage(fAccessorClassPackage, fAccessorClassName)) {
379 return false;
380 }
381
382 return (!Checks.resourceExists(getAccessorCUPath()));
383 }
384
385 public ICompilationUnit getAccessorCu() {
386 return fAccessorClassPackage.getCompilationUnit(getAccessorCUName());
387 }
388
389 public boolean willModifySource() {
390 NLSSubstitution[] subs= fSubstitutions;
391 for (int i= 0; i < subs.length; i++) {
392 if (subs[i].hasSourceChange())
393 return true;
394 }
395 return false;
396 }
397
398 public boolean willModifyPropertyFile() {
399 NLSSubstitution[] subs= fSubstitutions;
400 for (int i= 0; i < subs.length; i++) {
401 NLSSubstitution substitution= subs[i];
402 if (substitution.hasPropertyFileChange()) {
403 return true;
404 }
405 }
406 return false;
407 }
408
409 private boolean willModifyAccessorClass() {
410 if (!isEclipseNLS())
411 return false;
412
413 NLSSubstitution[] subs= fSubstitutions;
414 for (int i= 0; i < subs.length; i++) {
415 NLSSubstitution substitution= subs[i];
416 if (substitution.hasAccessorClassChange()) {
417 return true;
418 }
419 }
420 return false;
421 }
422
423 private boolean typeNameExistsInPackage(IPackageFragment pack, String name) throws JavaModelException {
424 return Checks.findTypeInPackage(pack, name) != null;
425 }
426
427 private String getAccessorCUName() {
428 return getAccessorClassName() + JavaModelUtil.DEFAULT_CU_SUFFIX;
429 }
430
431 public IPath getAccessorCUPath() {
432 return fAccessorClassPackage.getPath().append(getAccessorCUName());
433 }
434
435 public NLSSubstitution[] getSubstitutions() {
436 return fSubstitutions;
437 }
438
439 public String getPrefix() {
440 return fPrefix;
441 }
442
443 public void setPrefix(String prefix) {
444 fPrefix= prefix;
445 if (fSubstitutions != null) {
446 for (int i= 0; i < fSubstitutions.length; i++)
447 fSubstitutions[i].setPrefix(prefix);
448 }
449 }
450
451 public void setAccessorClassName(String name) {
452 Assert.isNotNull(name);
453 fAccessorClassName= name;
454 }
455
456 public void setAccessorClassPackage(IPackageFragment packageFragment) {
457 Assert.isNotNull(packageFragment);
458 fAccessorClassPackage= packageFragment;
459 }
460
461 /**
462 * Sets whether the Eclipse NLSing mechanism or
463 * standard resource bundle mechanism is used.
464 *
465 * @param isEclipseNLS <code>true</code> if NLSing is done the Eclipse way
466 * and <code>false</code> if the standard resource bundle mechanism is used
467 * @since 3.1
468 */
469 public void setIsEclipseNLS(boolean isEclipseNLS) {
470 fIsEclipseNLS= isEclipseNLS;
471 }
472
473 public void setResourceBundlePackage(IPackageFragment resourceBundlePackage) {
474 Assert.isNotNull(resourceBundlePackage);
475 fResourceBundlePackage= resourceBundlePackage;
476 }
477
478 public void setResourceBundleName(String resourceBundleName) {
479 Assert.isNotNull(resourceBundleName);
480 fResourceBundleName= resourceBundleName;
481 }
482
483 public IPackageFragment getAccessorClassPackage() {
484 return fAccessorClassPackage;
485 }
486
487 /**
488 * Computes whether the Eclipse NLSing mechanism is used.
489 *
490 * @return <code>true</code> if NLSing is done the Eclipse way
491 * and <code>false</code> if the standard resource bundle mechanism is used
492 * @since 3.1
493 */
494 public boolean detectIsEclipseNLS() {
495 ICompilationUnit accessorCU= getAccessorClassPackage().getCompilationUnit(getAccessorCUName());
496 IType type= accessorCU.getType(getAccessorClassName());
497 if (type.exists()) {
498 try {
499 String superclassName= type.getSuperclassName();
500 if (!"NLS".equals(superclassName) && !NLS.class.getName().equals(superclassName)) //$NON-NLS-1$
501 return false;
502 IType superclass= type.newSupertypeHierarchy(null).getSuperclass(type);
503 return superclass != null && NLS.class.getName().equals(superclass.getFullyQualifiedName());
504 } catch (JavaModelException e) {
505 // use default
506 }
507 }
508 // Bug 271375: Make the default be to use Eclipse's NLS mechanism if it's available.
509 return isEclipseNLSAvailable();
510 }
511
512 /**
513 * Returns whether the Eclipse NLSing mechanism or
514 * the standard resource bundle mechanism is used.
515 *
516 * @return <code>true</code> if NLSing is done the Eclipse way
517 * and <code>false</code> if the standard resource bundle mechanism is used
518 * @since 3.1
519 */
520 public boolean isEclipseNLS() {
521 return fIsEclipseNLS;
522 }
523
524 public IPackageFragment getResourceBundlePackage() {
525 return fResourceBundlePackage;
526 }
527
528 public String getAccessorClassName() {
529 return fAccessorClassName;
530 }
531
532 public String getResourceBundleName() {
533 return fResourceBundleName;
534 }
535
536 public void generated_9166475369688586640(NLSAccessorConfigurationDialog nlsaccessorconfigurationdialog) {
537 String accessorClassName= getAccessorClassName();
538
539 if (accessorClassName == null) {
540 accessorClassName= NLSRefactoring.DEFAULT_ACCESSOR_CLASSNAME;
541 }
542 nlsaccessorconfigurationdialog.fAccessorClassName.setText(accessorClassName);
543
544 nlsaccessorconfigurationdialog.fSubstitutionPattern.setText(getSubstitutionPattern());
545 }
546
547 public void generated_71626766676242111(NLSAccessorConfigurationDialog nlsaccessorconfigurationdialog) {
548 setAccessorClassPackage(nlsaccessorconfigurationdialog.fAccessorPackage.getSelected());
549 setAccessorClassName(nlsaccessorconfigurationdialog.fAccessorClassName.getText());
550
551 setResourceBundleName(nlsaccessorconfigurationdialog.fResourceBundleFile.getText());
552 setResourceBundlePackage(nlsaccessorconfigurationdialog.fResourceBundlePackage.getSelected());
553
554 if (!isEclipseNLS())
555 setSubstitutionPattern(nlsaccessorconfigurationdialog.fSubstitutionPattern.getText());
556
557 setIsEclipseNLS(detectIsEclipseNLS());
558 }
559
560 public void generated_4163567491581637506(ExternalizeWizardPage externalizewizardpage) {
561 externalizewizardpage.fSubstitutions= getSubstitutions();
562 externalizewizardpage.fNLSRefactoring= this;
563 }
564
565 public void generated_3731360844012260064(AccessorDescription selected) {
566 setResourceBundlePackage(selected.getResourceBundlePackage());
567 setIsEclipseNLS(detectIsEclipseNLS());
568 }
569
570 public String[] generated_1139376524781076216(ExternalizeWizardPage externalizewizardpage) {
571 AccessorDescription configured= new AccessorDescription(
572 getAccessorClassName(),
573 getAccessorClassPackage(),
574 getResourceBundleName(),
575 getResourceBundlePackage());
576
577 ArrayList<AccessorDescription> currChoices= new ArrayList<AccessorDescription>();
578 ArrayList<String> currLabels= new ArrayList<String>();
579
580 currChoices.add(configured);
581 currLabels.add(configured.getLabel());
582
583 AccessorDescription[] choices= externalizewizardpage.fAccessorChoices;
584 if (choices == null) {
585 choices= externalizewizardpage.loadAccessorDescriptions();
586 }
587
588 for (int i= 0; i < choices.length; i++) {
589 AccessorDescription curr= choices[i];
590 if (!curr.equals(configured)) {
591 currChoices.add(curr);
592 currLabels.add(curr.getLabel());
593 }
594 }
595
596 String[] labels= currLabels.toArray(new String[currLabels.size()]);
597 externalizewizardpage.fAccessorChoices= currChoices.toArray(new AccessorDescription[currChoices.size()]);
598 return labels;
599 }
600
601 public void generated_2664857242504905566(ExternalizeWizardPage externalizewizardpage) {
602 NLSAccessorConfigurationDialog dialog= new NLSAccessorConfigurationDialog(externalizewizardpage.getShell(), this);
603 if (dialog.open() == Window.OK) {
604 NLSSubstitution.updateSubtitutions(externalizewizardpage.fSubstitutions, externalizewizardpage.getProperties(getPropertyFileHandle()), getAccessorClassName());
605 if (externalizewizardpage.fIsEclipseNLS != null) {
606 externalizewizardpage.fIsEclipseNLS.setSelection(isEclipseNLS());
607 externalizewizardpage.fIsEclipseNLS.setEnabled(externalizewizardpage.willCreateAccessorClass());
608 }
609 externalizewizardpage.validateKeys(true);
610 externalizewizardpage.updateAccessorChoices();
611 }
612 }
613
614 public void generated_4392383387532617974(final ExternalizeWizardPage externalizewizardpage) {
615 externalizewizardpage.fPrefixField.setText(getPrefix());
616 externalizewizardpage.fPrefixField.selectAll();
617
618 externalizewizardpage.fPrefixField.addModifyListener(new ModifyListener() {
619 public void modifyText(ModifyEvent e) {
620 setPrefix(externalizewizardpage.fPrefixField.getText());
621 externalizewizardpage.validateKeys(true);
622 }
623 });
624 }
625
626 public void generated_4745418171921582296() {
627 if (isEclipseNLS()) {
628 setPrefix(getPrefix().replace('.', '_'));
629 } else {
630 setPrefix(getPrefix().replace('_', '.'));
631 }
632 }
633}