1 11 package org.eclipse.jdt.internal.corext.refactoring.nls; 12 13 import java.util.ArrayList ; 14 import java.util.List ; 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 BUNDLE_NAME= "BUNDLE_NAME"; public static final String PROPERTY_FILE_EXT= ".properties"; public static final String DEFAULT_ACCESSOR_CLASSNAME= "Messages"; 55 public static final String KEY= "${key}"; public static final String DEFAULT_SUBST_PATTERN= "getString(" + KEY + ")"; 58 public static final String DEFAULT_PROPERTY_FILENAME= "messages"; 60 62 private String fAccessorClassName; 63 private IPackageFragment fAccessorClassPackage; 64 private String fResourceBundleName; 65 private IPackageFragment fResourceBundlePackage; 66 67 private String fSubstitutionPattern; 68 private ICompilationUnit fCu; 69 private NLSSubstitution[] fSubstitutions; 70 71 private String fPrefix; 72 73 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 cuName= fCu.getElementName(); 95 if (fIsEclipseNLS) 96 setPrefix(cuName.substring(0, cuName.length() - 5) + "_"); else 98 setPrefix(cuName.substring(0, cuName.length() - 4)); } 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 116 public void setSubstitutionPattern(String pattern) { 117 Assert.isNotNull(pattern); 118 fSubstitutionPattern= pattern; 119 } 120 121 124 public String 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 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 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 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); 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 Assert.isNotNull(fAccessorClassName); 238 Assert.isNotNull(getSubstitutionPattern()); 239 } 240 241 private IFile[] getAllFilesToModify() { 242 243 List files= new ArrayList (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 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 pattern= getSubstitutionPattern(); 310 311 RefactoringStatus result= new RefactoringStatus(); 312 if (pattern.trim().length() == 0) { result.addError(NLSMessages.NLSRefactoring_pattern_empty); 314 } 315 316 if (pattern.indexOf(KEY) == -1) { 317 String 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 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 key) { 342 RefactoringStatus result= new RefactoringStatus(); 343 344 if (key == null) 345 result.addFatalError(NLSMessages.NLSRefactoring_null); 346 347 if (key.startsWith("!") || key.startsWith("#")) { RefactoringStatusContext context= new JavaStringStatusContext(key, new SourceRange(0, 0)); 349 result.addWarning(NLSMessages.NLSRefactoring_warning, context); 350 } 351 352 if ("".equals(key.trim())) result.addFatalError(NLSMessages.NLSRefactoring_empty); 354 355 final String [] UNWANTED_STRINGS= {" ", ":", "\"", "\\", "'", "?", "="}; for (int i= 0; i < UNWANTED_STRINGS.length; i++) { 358 if (key.indexOf(UNWANTED_STRINGS[i]) != -1) { 359 String [] args= {key, UNWANTED_STRINGS[i]}; 360 String 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 name) throws JavaModelException { 420 return Checks.findTypeInPackage(pack, name) != null; 421 } 422 423 private String 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 getPrefix() { 436 return fPrefix; 437 } 438 439 public void setPrefix(String 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 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 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 resourceBundleName) { 475 Assert.isNotNull(resourceBundleName); 476 fResourceBundleName= resourceBundleName; 477 } 478 479 public IPackageFragment getAccessorClassPackage() { 480 return fAccessorClassPackage; 481 } 482 483 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 superclassName= type.getSuperclassName(); 497 if (!"NLS".equals(superclassName) && !NLS.class.getName().equals(superclassName)) 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 517 public boolean isEclipseNLS() { 518 return fIsEclipseNLS; 519 } 520 521 public IPackageFragment getResourceBundlePackage() { 522 return fResourceBundlePackage; 523 } 524 525 public String getAccessorClassName() { 526 return fAccessorClassName; 527 } 528 529 public String getResourceBundleName() { 530 return fResourceBundleName; 531 } 532 } 533 | Popular Tags |