KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.Arrays JavaDoc;
14
15 import org.eclipse.text.edits.DeleteEdit;
16 import org.eclipse.text.edits.InsertEdit;
17 import org.eclipse.text.edits.MultiTextEdit;
18 import org.eclipse.text.edits.ReplaceEdit;
19 import org.eclipse.text.edits.TextEdit;
20
21 import org.eclipse.core.runtime.CoreException;
22
23 import org.eclipse.jface.text.Region;
24 import org.eclipse.jface.text.TextUtilities;
25
26 import org.eclipse.ltk.core.refactoring.Change;
27 import org.eclipse.ltk.core.refactoring.TextChange;
28
29 import org.eclipse.jdt.core.IBuffer;
30 import org.eclipse.jdt.core.ICompilationUnit;
31 import org.eclipse.jdt.core.IPackageFragment;
32 import org.eclipse.jdt.core.IType;
33 import org.eclipse.jdt.core.compiler.InvalidInputException;
34 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
35
36 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
37 import org.eclipse.jdt.internal.corext.refactoring.changes.CompilationUnitChange;
38 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
39 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
40 import org.eclipse.jdt.internal.corext.util.Messages;
41
42 public class NLSSourceModifier {
43
44     private final String JavaDoc fSubstitutionPattern;
45     private final boolean fIsEclipseNLS;
46
47     private NLSSourceModifier(String JavaDoc substitutionPattern, boolean isEclipseNLS) {
48         fSubstitutionPattern= substitutionPattern;
49         fIsEclipseNLS= isEclipseNLS;
50     }
51
52     public static Change create(ICompilationUnit cu, NLSSubstitution[] subs, String JavaDoc substitutionPattern, IPackageFragment accessorPackage, String JavaDoc accessorClassName, boolean isEclipseNLS) throws CoreException {
53
54         NLSSourceModifier sourceModification= new NLSSourceModifier(substitutionPattern, isEclipseNLS);
55
56         String JavaDoc message= Messages.format(NLSMessages.NLSSourceModifier_change_description, cu.getElementName());
57
58         TextChange change= new CompilationUnitChange(message, cu);
59         MultiTextEdit multiTextEdit= new MultiTextEdit();
60         change.setEdit(multiTextEdit);
61
62         accessorClassName= sourceModification.createImportForAccessor(multiTextEdit, accessorClassName, accessorPackage, cu);
63
64         for (int i= 0; i < subs.length; i++) {
65             NLSSubstitution substitution= subs[i];
66             int newState= substitution.getState();
67             if (substitution.hasStateChanged()) {
68                 if (newState == NLSSubstitution.EXTERNALIZED) {
69                     if (substitution.getInitialState() == NLSSubstitution.INTERNALIZED) {
70                         sourceModification.addNLS(substitution, change, accessorClassName);
71                     } else if (substitution.getInitialState() == NLSSubstitution.IGNORED) {
72                         sourceModification.addAccessor(substitution, change, accessorClassName);
73                     }
74                 } else if (newState == NLSSubstitution.INTERNALIZED) {
75                     if (substitution.getInitialState() == NLSSubstitution.IGNORED) {
76                         sourceModification.deleteTag(substitution, change);
77                         if (substitution.isValueRename()) {
78                             sourceModification.replaceValue(substitution, change);
79                         }
80                     } else if (substitution.getInitialState() == NLSSubstitution.EXTERNALIZED) {
81                         sourceModification.deleteAccessor(substitution, change, cu);
82                         if (!isEclipseNLS)
83                             sourceModification.deleteTag(substitution, change);
84                     }
85                 } else if (newState == NLSSubstitution.IGNORED) {
86                     if (substitution.getInitialState() == NLSSubstitution.INTERNALIZED) {
87                         sourceModification.addNLS(substitution, change, accessorClassName);
88                         if (substitution.isValueRename()) {
89                             sourceModification.replaceValue(substitution, change);
90                         }
91                     } else {
92                         if (substitution.getInitialState() == NLSSubstitution.EXTERNALIZED) {
93                             sourceModification.deleteAccessor(substitution, change, cu);
94                         }
95                     }
96                     }
97             } else {
98                 if (newState == NLSSubstitution.EXTERNALIZED) {
99                     if (substitution.isKeyRename()) {
100                         sourceModification.replaceKey(substitution, change);
101                     }
102                     if (substitution.isAccessorRename()) {
103                         sourceModification.replaceAccessor(substitution, change);
104                     }
105                 } else {
106                     if (substitution.isValueRename()) {
107                         sourceModification.replaceValue(substitution, change);
108                     }
109                 }
110             }
111         }
112
113         return change;
114     }
115
116     /**
117      * @param substitution
118      * @param change
119      */

120     private void replaceAccessor(NLSSubstitution substitution, TextChange change) {
121         AccessorClassReference accessorClassRef= substitution.getAccessorClassReference();
122         if (accessorClassRef != null) {
123             Region region= accessorClassRef.getRegion();
124             int len= accessorClassRef.getName().length();
125             String JavaDoc[] args= {accessorClassRef.getName(), substitution.getUpdatedAccessor()};
126             TextChangeCompatibility.addTextEdit(change, Messages.format(NLSMessages.NLSSourceModifier_replace_accessor, args),
127                     new ReplaceEdit(region.getOffset(), len, substitution.getUpdatedAccessor())); //
128
}
129         
130     }
131
132     private void replaceKey(NLSSubstitution substitution, TextChange change) {
133         Region region= substitution.getNLSElement().getPosition();
134         String JavaDoc[] args= {substitution.getInitialKey(), substitution.getKey()};
135         
136         ReplaceEdit replaceEdit;
137         if (fIsEclipseNLS)
138             replaceEdit= new ReplaceEdit(region.getOffset(), region.getLength(), substitution.getKey());
139         else
140             replaceEdit= new ReplaceEdit(region.getOffset(), region.getLength(), '\"' + unwindEscapeChars(substitution.getKey()) + '\"'); //
141

142         TextChangeCompatibility.addTextEdit(change, Messages.format(NLSMessages.NLSSourceModifier_replace_key, args), replaceEdit);
143     }
144     
145     private void replaceValue(NLSSubstitution substitution, TextChange change) {
146         Region region= substitution.getNLSElement().getPosition();
147         String JavaDoc[] args= {substitution.getInitialValue(), substitution.getValueNonEmpty()};
148         TextChangeCompatibility.addTextEdit(change, Messages.format(NLSMessages.NLSSourceModifier_replace_value, args),
149                 new ReplaceEdit(region.getOffset(), region.getLength(), '\"' + unwindEscapeChars(substitution.getValueNonEmpty()) + '\"')); //
150
}
151
152     private void deleteAccessor(NLSSubstitution substitution, TextChange change, ICompilationUnit cu) throws CoreException {
153         AccessorClassReference accessorClassRef= substitution.getAccessorClassReference();
154         if (accessorClassRef != null) {
155             Region region= accessorClassRef.getRegion();
156             String JavaDoc[] args= {substitution.getValueNonEmpty(), substitution.getKey()};
157             String JavaDoc label= Messages.format(NLSMessages.NLSSourceModifier_remove_accessor, args);
158             String JavaDoc replaceString= '\"' + unwindEscapeChars(substitution.getValueNonEmpty()) + '\"';
159             TextChangeCompatibility.addTextEdit(change, label, new ReplaceEdit(region.getOffset(), region.getLength(), replaceString));
160             if (fIsEclipseNLS && substitution.getState() != NLSSubstitution.INTERNALIZED) {
161                 
162                 Region position= substitution.getNLSElement().getPosition();
163                 int lineStart= getLineStart(cu.getBuffer(), position.getOffset());
164                 int lineEnd= getLineEnd(cu.getBuffer(), position.getOffset());
165                 String JavaDoc cuLine= cu.getBuffer().getText(lineStart, lineEnd - lineStart);
166                 StringBuffer JavaDoc buf= new StringBuffer JavaDoc(cuLine);
167                 buf.replace(region.getOffset() - lineStart, region.getOffset() + region.getLength() - lineStart, replaceString);
168                 try {
169                     NLSLine[] allLines= NLSScanner.scan(buf.toString());
170                     
171                     NLSLine nlsLine= allLines[0];
172                     NLSElement element= findElement(nlsLine, position.getOffset() - lineStart - accessorClassRef.getName().length() - 1);
173                     if (element == null || element.hasTag())
174                         return;
175                     
176                     NLSElement[] elements= nlsLine.getElements();
177                     int indexInElementList= Arrays.asList(elements).indexOf(element);
178                     String JavaDoc editText= ' ' + NLSElement.createTagText(indexInElementList + 1); //tags are 1-based
179
TextChangeCompatibility.addTextEdit(change, label, new InsertEdit(lineEnd, editText));
180
181                 } catch (InvalidInputException e) {
182                     
183                 }
184             }
185         }
186     }
187
188     private int getLineEnd(IBuffer buffer, int offset) {
189         int pos= offset;
190         int length= buffer.getLength();
191         while (pos < length && !isDelemiter(buffer.getChar(pos))) {
192             pos++;
193         }
194         return pos;
195     }
196
197     private int getLineStart(IBuffer buffer, int offset) {
198         int pos= offset;
199         while (pos >= 0 && !isDelemiter(buffer.getChar(pos))) {
200             pos--;
201         }
202         return pos + 1;
203     }
204
205     private boolean isDelemiter(char ch) {
206         String JavaDoc[] delem= TextUtilities.DELIMITERS;
207         for (int i= 0; i < delem.length; i++) {
208             if (delem[i].length() == 1 && ch == delem[i].charAt(0))
209                 return true;
210         }
211         return false;
212     }
213     
214     private static boolean isPositionInElement(NLSElement element, int position) {
215         Region elementPosition= element.getPosition();
216         return (elementPosition.getOffset() <= position && position <= elementPosition.getOffset() + elementPosition.getLength());
217     }
218
219     private static NLSElement findElement(NLSLine line, int position) {
220         NLSElement[] elements= line.getElements();
221         for (int i= 0; i < elements.length; i++) {
222             NLSElement element= elements[i];
223             if (isPositionInElement(element, position))
224                 return element;
225         }
226         return null;
227     }
228
229     // TODO: not dry
230
private String JavaDoc unwindEscapeChars(String JavaDoc s) {
231         StringBuffer JavaDoc sb= new StringBuffer JavaDoc(s.length());
232         int length= s.length();
233         for (int i= 0; i < length; i++) {
234             char c= s.charAt(i);
235             sb.append(getUnwoundString(c));
236         }
237         return sb.toString();
238     }
239
240     private String JavaDoc getUnwoundString(char c) {
241         switch (c) {
242             case '\b' :
243                 return "\\b";//$NON-NLS-1$
244
case '\t' :
245                 return "\\t";//$NON-NLS-1$
246
case '\n' :
247                 return "\\n";//$NON-NLS-1$
248
case '\f' :
249                 return "\\f";//$NON-NLS-1$
250
case '\r' :
251                 return "\\r";//$NON-NLS-1$
252
case '\\' :
253                 return "\\\\";//$NON-NLS-1$
254
}
255         return String.valueOf(c);
256     }
257
258     private void deleteTag(NLSSubstitution substitution, TextChange change) {
259         Region textRegion= substitution.getNLSElement().getTagPosition();
260
261         TextChangeCompatibility.addTextEdit(change, NLSMessages.NLSSourceModifier_remove_tag,
262                 new DeleteEdit(textRegion.getOffset(), textRegion.getLength()));
263     }
264
265     private String JavaDoc createImportForAccessor(MultiTextEdit parent, String JavaDoc accessorClassName, IPackageFragment accessorPackage, ICompilationUnit cu) throws CoreException {
266         IType type= accessorPackage.getCompilationUnit(accessorClassName + JavaModelUtil.DEFAULT_CU_SUFFIX).getType(accessorClassName);
267         String JavaDoc fullyQualifiedName= type.getFullyQualifiedName();
268
269         ImportRewrite importRewrite= StubUtility.createImportRewrite(cu, true);
270         String JavaDoc nameToUse= importRewrite.addImport(fullyQualifiedName);
271         TextEdit edit= importRewrite.rewriteImports(null);
272         parent.addChild(edit);
273
274         return nameToUse;
275     }
276
277     private void addNLS(NLSSubstitution sub, TextChange change, String JavaDoc accessorName) {
278         if (sub.getState() == NLSSubstitution.INTERNALIZED)
279             return;
280         
281         NLSElement element= sub.getNLSElement();
282
283         addAccessor(sub, change, accessorName);
284         
285         if (!fIsEclipseNLS || sub.getState() == NLSSubstitution.IGNORED) {
286             // Add $NON-NLS-n tag
287
String JavaDoc arg= sub.getState() == NLSSubstitution.EXTERNALIZED ? sub.getKey() : sub.getValueNonEmpty();
288             String JavaDoc name= Messages.format(NLSMessages.NLSSourceModifier_add_tag, arg);
289             TextChangeCompatibility.addTextEdit(change, name, createAddTagChange(element));
290         }
291     }
292
293     private void addAccessor(NLSSubstitution sub, TextChange change, String JavaDoc accessorName) {
294         if (sub.getState() == NLSSubstitution.EXTERNALIZED) {
295             NLSElement element= sub.getNLSElement();
296             Region position= element.getPosition();
297             String JavaDoc[] args= {sub.getValueNonEmpty(), sub.getKey()};
298             String JavaDoc text= Messages.format(NLSMessages.NLSSourceModifier_externalize, args);
299
300             String JavaDoc resourceGetter= createResourceGetter(sub.getKey(), accessorName);
301             
302             TextEdit edit= new ReplaceEdit(position.getOffset(), position.getLength(), resourceGetter);
303             if (fIsEclipseNLS && element.getTagPosition() != null) {
304                 MultiTextEdit multiEdit= new MultiTextEdit();
305                 multiEdit.addChild(edit);
306                 Region tagPosition= element.getTagPosition();
307                 multiEdit.addChild(new DeleteEdit(tagPosition.getOffset(), tagPosition.getLength()));
308                 edit= multiEdit;
309             }
310             TextChangeCompatibility.addTextEdit(change, text, edit);
311         }
312     }
313
314     private TextEdit createAddTagChange(NLSElement element) {
315         int offset= element.getTagPosition().getOffset(); //to be changed
316
String JavaDoc text= ' ' + element.getTagText();
317         return new InsertEdit(offset, text);
318     }
319
320     private String JavaDoc createResourceGetter(String JavaDoc key, String JavaDoc accessorName) {
321         StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
322         buf.append(accessorName);
323         buf.append('.');
324         
325         if (fIsEclipseNLS)
326             buf.append(key);
327         else {
328             //we just replace the first occurrence of KEY in the pattern
329
int i= fSubstitutionPattern.indexOf(NLSRefactoring.KEY);
330             if (i != -1) {
331                 buf.append(fSubstitutionPattern.substring(0, i));
332                 buf.append('"').append(key).append('"');
333                 buf.append(fSubstitutionPattern.substring(i + NLSRefactoring.KEY.length()));
334             }
335         }
336         return buf.toString();
337     }
338 }
339
Popular Tags