]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/nls/NLSHintHelper.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / nls / NLSHintHelper.java
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  *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.refactoring.nls;
12
13 import java.io.ByteArrayInputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Properties;
21
22 import org.eclipse.core.runtime.CoreException;
23
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IStorage;
26
27 import org.eclipse.core.filebuffers.FileBuffers;
28 import org.eclipse.core.filebuffers.ITextFileBuffer;
29 import org.eclipse.core.filebuffers.ITextFileBufferManager;
30 import org.eclipse.core.filebuffers.LocationKind;
31
32 import org.eclipse.jface.text.IDocument;
33 import org.eclipse.jface.text.IRegion;
34 import org.eclipse.jface.text.Region;
35
36 import org.eclipse.jdt.core.ICompilationUnit;
37 import org.eclipse.jdt.core.IJavaElement;
38 import org.eclipse.jdt.core.IJavaProject;
39 import org.eclipse.jdt.core.IPackageFragment;
40 import org.eclipse.jdt.core.IPackageFragmentRoot;
41 import org.eclipse.jdt.core.IType;
42 import org.eclipse.jdt.core.ITypeRoot;
43 import org.eclipse.jdt.core.JavaModelException;
44 import org.eclipse.jdt.core.Signature;
45 import org.eclipse.jdt.core.dom.ASTNode;
46 import org.eclipse.jdt.core.dom.ASTVisitor;
47 import org.eclipse.jdt.core.dom.Assignment;
48 import org.eclipse.jdt.core.dom.CompilationUnit;
49 import org.eclipse.jdt.core.dom.Expression;
50 import org.eclipse.jdt.core.dom.IBinding;
51 import org.eclipse.jdt.core.dom.IMethodBinding;
52 import org.eclipse.jdt.core.dom.ITypeBinding;
53 import org.eclipse.jdt.core.dom.IVariableBinding;
54 import org.eclipse.jdt.core.dom.MethodInvocation;
55 import org.eclipse.jdt.core.dom.Modifier;
56 import org.eclipse.jdt.core.dom.Name;
57 import org.eclipse.jdt.core.dom.NodeFinder;
58 import org.eclipse.jdt.core.dom.QualifiedName;
59 import org.eclipse.jdt.core.dom.SimpleName;
60 import org.eclipse.jdt.core.dom.SimpleType;
61 import org.eclipse.jdt.core.dom.StringLiteral;
62 import org.eclipse.jdt.core.dom.TypeLiteral;
63 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
64
65 import org.eclipse.jdt.internal.corext.dom.Bindings;
66 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
67
68 import org.eclipse.jdt.ui.SharedASTProvider;
69
70 import org.eclipse.jdt.internal.ui.JavaPlugin;
71
72 public class NLSHintHelper {
73
74         private NLSHintHelper() {
75         }
76
77         /**
78          * Returns the accessor binding info or <code>null</code> if this element is not a nls'ed entry
79          *
80          * @param astRoot the ast root
81          * @param nlsElement the nls element
82          * @return the accessor class reference or <code>null</code> if this element is not a nls'ed entry
83          */
84         public static AccessorClassReference getAccessorClassReference(CompilationUnit astRoot, NLSElement nlsElement) {
85                 IRegion region= nlsElement.getPosition();
86                 return getAccessorClassReference(astRoot, region);
87         }
88
89         /**
90          * Returns the accessor binding info or <code>null</code> if this element is not a nls'ed entry
91          *
92          * @param astRoot the ast root
93          * @param region the text region
94          * @return the accessor class reference or <code>null</code> if this element is not a nls'ed entry
95          */
96         public static AccessorClassReference getAccessorClassReference(CompilationUnit astRoot, IRegion region) {
97                 return getAccessorClassReference(astRoot, region, false);
98         }
99
100         /**
101          * Returns the accessor binding info or <code>null</code> if this element is not a nls'ed entry
102          * 
103          * @param astRoot the ast root
104          * @param region the text region
105          * @param usedFullyQualifiedName boolean flag to indicate that fully qualified name is used to
106          *            refer a NLS key string constant
107          * @return the accessor class reference or <code>null</code> if this element is not a nls'ed
108          *         entry
109          */
110         public static AccessorClassReference getAccessorClassReference(CompilationUnit astRoot, IRegion region, boolean usedFullyQualifiedName) {
111                 ASTNode nlsStringLiteral= NodeFinder.perform(astRoot, region.getOffset(), region.getLength());
112                 if (nlsStringLiteral == null)
113                         return null; // not found
114
115                 ASTNode parent= nlsStringLiteral.getParent();
116                 if (usedFullyQualifiedName) {
117                         parent= parent.getParent();
118                 }
119
120                 ITypeBinding accessorBinding= null;
121
122                 if (!usedFullyQualifiedName && nlsStringLiteral instanceof SimpleName && nlsStringLiteral.getLocationInParent() == QualifiedName.NAME_PROPERTY) {
123                         SimpleName name= (SimpleName)nlsStringLiteral;
124
125                         IBinding binding= name.resolveBinding();
126                         if (binding instanceof IVariableBinding) {
127                                 IVariableBinding variableBinding= (IVariableBinding)binding;
128                                 if (Modifier.isStatic(variableBinding.getModifiers()))
129                                         accessorBinding= variableBinding.getDeclaringClass();
130                         }
131                 }
132
133                 if (accessorBinding == null) {
134
135                         if (parent instanceof MethodInvocation) {
136                                 MethodInvocation methodInvocation= (MethodInvocation) parent;
137                                 List<Expression> args= methodInvocation.arguments();
138                                 if (args.size() != 1 && args.indexOf(nlsStringLiteral) != 0) {
139                                         return null; // must be the only argument in lookup method
140                                 }
141
142                                 Expression firstArgument= args.get(0);
143                                 ITypeBinding argumentBinding= firstArgument.resolveTypeBinding();
144                                 if (argumentBinding == null || !argumentBinding.getQualifiedName().equals("java.lang.String")) { //$NON-NLS-1$
145                                         return null;
146                                 }
147
148                                 ITypeBinding typeBinding= methodInvocation.resolveTypeBinding();
149                                 if (typeBinding == null || !typeBinding.getQualifiedName().equals("java.lang.String")) { //$NON-NLS-1$
150                                         return null;
151                                 }
152
153                                 IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
154                                 if (methodBinding == null || !Modifier.isStatic(methodBinding.getModifiers())) {
155                                         return null; // only static methods qualify
156                                 }
157
158                                 accessorBinding= methodBinding.getDeclaringClass();
159                         } else if (parent instanceof VariableDeclarationFragment) {
160                                 VariableDeclarationFragment decl= (VariableDeclarationFragment)parent;
161                                 if (decl.getInitializer() != null)
162                                         return null;
163
164                                 IBinding binding= decl.resolveBinding();
165                                 if (!(binding instanceof IVariableBinding))
166                                         return null;
167
168                                 IVariableBinding variableBinding= (IVariableBinding)binding;
169                                 if (!Modifier.isStatic(variableBinding.getModifiers()))
170                                         return null;
171
172                                 accessorBinding= variableBinding.getDeclaringClass();
173                         }
174                 }
175
176                 if (accessorBinding == null)
177                         return null;
178
179                 String resourceBundleName;
180                 resourceBundleName= getResourceBundleName(accessorBinding);
181
182                 if (resourceBundleName != null)
183                         return new AccessorClassReference(accessorBinding, resourceBundleName, new Region(parent.getStartPosition(), parent.getLength()));
184
185                 return null;
186         }
187
188         public static IPackageFragment getPackageOfAccessorClass(IJavaProject javaProject, ITypeBinding accessorBinding) throws JavaModelException {
189                 if (accessorBinding != null) {
190                         ICompilationUnit unit= Bindings.findCompilationUnit(accessorBinding, javaProject);
191                         if (unit != null) {
192                                 return (IPackageFragment) unit.getParent();
193                         }
194                 }
195                 return null;
196         }
197
198         public static String getResourceBundleName(ITypeBinding accessorClassBinding) {
199                 IJavaElement je= accessorClassBinding.getJavaElement();
200                 if (!(je instanceof IType))
201                         return null;
202                 ITypeRoot typeRoot= ((IType) je).getTypeRoot();
203                 CompilationUnit astRoot= SharedASTProvider.getAST(typeRoot, SharedASTProvider.WAIT_YES, null);
204
205                 return getResourceBundleName(astRoot);
206         }
207
208         public static String getResourceBundleName(ITypeRoot input) {
209                 return getResourceBundleName(SharedASTProvider.getAST(input, SharedASTProvider.WAIT_YES, null));
210         }
211
212         public static String getResourceBundleName(CompilationUnit astRoot) {
213
214                 if (astRoot == null)
215                         return null;
216
217                 final Map<Object, Object> resultCollector= new HashMap<Object, Object>(5);
218                 final Object RESULT_KEY= new Object();
219                 final Object FIELD_KEY= new Object();
220
221                 astRoot.accept(new ASTVisitor() {
222
223                         @Override
224                         public boolean visit(MethodInvocation node) {
225                                 IMethodBinding method= node.resolveMethodBinding();
226                                 if (method == null)
227                                         return true;
228
229                                 String name= method.getDeclaringClass().getQualifiedName();
230                                 if (!("java.util.ResourceBundle".equals(name) && "getBundle".equals(method.getName()) && node.arguments().size() > 0) && //old school //$NON-NLS-1$ //$NON-NLS-2$
231                                                 !("org.eclipse.osgi.util.NLS".equals(name) && "initializeMessages".equals(method.getName()) && node.arguments().size() == 2)) //Eclipse style //$NON-NLS-1$ //$NON-NLS-2$
232                                         return true;
233
234                                 Expression argument= (Expression)node.arguments().get(0);
235                                 String bundleName= getBundleName(argument);
236                                 if (bundleName != null)
237                                         resultCollector.put(RESULT_KEY, bundleName);
238
239                                 if (argument instanceof Name) {
240                                         Object fieldNameBinding= ((Name)argument).resolveBinding();
241                                         if (fieldNameBinding != null)
242                                                 resultCollector.put(FIELD_KEY, fieldNameBinding);
243                                 }
244
245                                 return false;
246                         }
247
248                         @Override
249                         public boolean visit(VariableDeclarationFragment node) {
250                                 Expression initializer= node.getInitializer();
251                                 String bundleName= getBundleName(initializer);
252                                 if (bundleName != null) {
253                                         Object fieldNameBinding= node.getName().resolveBinding();
254                                         if (fieldNameBinding != null)
255                                                 resultCollector.put(fieldNameBinding, bundleName);
256                                         return false;
257                                 }
258                                 return true;
259                         }
260
261                         @Override
262                         public boolean visit(Assignment node) {
263                                 if (node.getLeftHandSide() instanceof Name) {
264                                         String bundleName= getBundleName(node.getRightHandSide());
265                                         if (bundleName != null) {
266                                                 Object fieldNameBinding= ((Name)node.getLeftHandSide()).resolveBinding();
267                                                 if (fieldNameBinding != null) {
268                                                         resultCollector.put(fieldNameBinding, bundleName);
269                                                         return false;
270                                                 }
271                                         }
272                                 }
273                                 return true;
274                         }
275
276                         private String getBundleName(Expression initializer) {
277                                 if (initializer instanceof StringLiteral)
278                                         return ((StringLiteral)initializer).getLiteralValue();
279
280                                 if (initializer instanceof MethodInvocation) {
281                                         MethodInvocation methInvocation= (MethodInvocation)initializer;
282                                         Expression exp= methInvocation.getExpression();
283                                         if ((exp != null) && (exp instanceof TypeLiteral)) {
284                                                 SimpleType simple= (SimpleType)((TypeLiteral) exp).getType();
285                                                 ITypeBinding typeBinding= simple.resolveBinding();
286                                                 if (typeBinding != null)
287                                                         return typeBinding.getQualifiedName();
288                                         }
289                                 }
290                                 return null;
291                         }
292
293                 });
294
295
296                 Object fieldName;
297                 String result;
298
299                 result= (String)resultCollector.get(RESULT_KEY);
300                 if (result != null)
301                         return result;
302
303                 fieldName= resultCollector.get(FIELD_KEY);
304                 if (fieldName != null)
305                         return (String)resultCollector.get(fieldName);
306
307                 // Now try hard-coded bundle name String field names from NLS tooling:
308                 Iterator<Object> iter= resultCollector.keySet().iterator();
309                 while (iter.hasNext()) {
310                         Object o= iter.next();
311                         if (!(o instanceof IBinding))
312                                 continue;
313                         IBinding binding= (IBinding)o;
314                         fieldName= binding.getName();
315                         if (fieldName.equals("BUNDLE_NAME") || fieldName.equals("RESOURCE_BUNDLE") || fieldName.equals("bundleName")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
316                                 result= (String)resultCollector.get(binding);
317                                 if (result != null)
318                                         return result;
319                         }
320                 }
321
322                 result= (String)resultCollector.get(RESULT_KEY);
323                 if (result != null)
324                         return result;
325
326                 fieldName= resultCollector.get(FIELD_KEY);
327                 if (fieldName != null)
328                         return (String)resultCollector.get(fieldName);
329
330                 return null;
331         }
332
333         public static IPackageFragment getResourceBundlePackage(IJavaProject javaProject, String packageName, String resourceName) throws JavaModelException {
334                 IPackageFragmentRoot[] allRoots= javaProject.getAllPackageFragmentRoots();
335                 for (int i= 0; i < allRoots.length; i++) {
336                         IPackageFragmentRoot root= allRoots[i];
337                         if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
338                                 IPackageFragment packageFragment= root.getPackageFragment(packageName);
339                                 if (packageFragment.exists()) {
340                                         Object[] resources= packageFragment.isDefaultPackage() ? root.getNonJavaResources() : packageFragment.getNonJavaResources();
341                                         for (int j= 0; j < resources.length; j++) {
342                                                 Object object= resources[j];
343                                                 if (object instanceof IFile) {
344                                                         IFile file= (IFile) object;
345                                                         if (file.getName().equals(resourceName)) {
346                                                                 return packageFragment;
347                                                         }
348                                                 }
349                                         }
350                                 }
351                         }
352                 }
353                 return null;
354         }
355
356         public static IStorage getResourceBundle(ICompilationUnit compilationUnit) throws JavaModelException {
357                 IJavaProject project= compilationUnit.getJavaProject();
358                 if (project == null)
359                         return null;
360
361                 String name= getResourceBundleName(compilationUnit);
362                 if (name == null)
363                         return null;
364
365                 String packName= Signature.getQualifier(name);
366                 String resourceName= Signature.getSimpleName(name) + NLSRefactoring.PROPERTY_FILE_EXT;
367
368                 return getResourceBundle(project, packName, resourceName);
369         }
370
371         public static IStorage getResourceBundle(IJavaProject javaProject, String packageName, String resourceName) throws JavaModelException {
372                 IPackageFragmentRoot[] allRoots= javaProject.getAllPackageFragmentRoots();
373                 for (int i= 0; i < allRoots.length; i++) {
374                         IPackageFragmentRoot root= allRoots[i];
375                         if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
376                                 IStorage storage= getResourceBundle(root, packageName, resourceName);
377                                 if (storage != null)
378                                         return storage;
379                         }
380                 }
381                 return null;
382         }
383
384         public static IStorage getResourceBundle(IPackageFragmentRoot root, String packageName, String resourceName) throws JavaModelException {
385                 IPackageFragment packageFragment= root.getPackageFragment(packageName);
386                 if (packageFragment.exists()) {
387                         Object[] resources= packageFragment.isDefaultPackage() ? root.getNonJavaResources() : packageFragment.getNonJavaResources();
388                         for (int j= 0; j < resources.length; j++) {
389                                 Object object= resources[j];
390                                 if (JavaModelUtil.isOpenableStorage(object)) {
391                                         IStorage storage= (IStorage)object;
392                                         if (storage.getName().equals(resourceName)) {
393                                                 return storage;
394                                         }
395                                 }
396                         }
397                 }
398                 return null;
399         }
400
401         public static IStorage getResourceBundle(IJavaProject javaProject, AccessorClassReference accessorClassReference) throws JavaModelException {
402                 String resourceBundle= accessorClassReference.getResourceBundleName();
403                 if (resourceBundle == null)
404                         return null;
405
406                 String resourceName= Signature.getSimpleName(resourceBundle) + NLSRefactoring.PROPERTY_FILE_EXT;
407                 String packName= Signature.getQualifier(resourceBundle);
408                 ITypeBinding accessorClass= accessorClassReference.getBinding();
409
410                 if (accessorClass.isFromSource())
411                         return getResourceBundle(javaProject, packName, resourceName);
412                 else if (accessorClass.getJavaElement() != null)
413                         return getResourceBundle((IPackageFragmentRoot)accessorClass.getJavaElement().getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT), packName, resourceName);
414
415                 return null;
416         }
417
418         /**
419          * Reads the properties from the given storage and
420          * returns it.
421          *
422          * @param javaProject the Java project
423          * @param accessorClassReference the accessor class reference
424          * @return the properties or <code>null</code> if it was not successfully read
425          */
426         public static Properties getProperties(IJavaProject javaProject, AccessorClassReference accessorClassReference) {
427                 try {
428                         IStorage storage= NLSHintHelper.getResourceBundle(javaProject, accessorClassReference);
429                         return getProperties(storage);
430                 } catch (JavaModelException ex) {
431                         // sorry no properties
432                         return null;
433                 }
434         }
435
436         /**
437          * Reads the properties from the given storage and
438          * returns it.
439          *
440          * @param storage the storage
441          * @return the properties or <code>null</code> if it was not successfully read
442          */
443         public static Properties getProperties(IStorage storage) {
444                 if (storage == null)
445                         return null;
446
447                 Properties props= new Properties();
448                 InputStream is= null;
449
450                 ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
451                 try {
452                         if (manager != null) {
453                                 ITextFileBuffer buffer= manager.getTextFileBuffer(storage.getFullPath(), LocationKind.NORMALIZE);
454                                 if (buffer != null) {
455                                         IDocument document= buffer.getDocument();
456                                         is= new ByteArrayInputStream(document.get().getBytes());
457                                 }
458                         }
459
460                         // Fallback: read from storage
461                         if (is == null)
462                                 is= storage.getContents();
463
464                         props.load(is);
465
466                 } catch (IOException e) {
467                         // sorry no properties
468                         return null;
469                 } catch (CoreException e) {
470                         // sorry no properties
471                         return null;
472                 } finally {
473                         if (is != null) try {
474                                 is.close();
475                         } catch (IOException e) {
476                                 // return properties anyway but log
477                                 JavaPlugin.log(e);
478                         }
479                 }
480                 return props;
481         }
482
483 }