KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.text.edits.DeleteEdit;
18 import org.eclipse.text.edits.InsertEdit;
19 import org.eclipse.text.edits.ReplaceEdit;
20
21 import org.eclipse.jface.text.BadLocationException;
22 import org.eclipse.jface.text.IDocument;
23 import org.eclipse.jface.text.TextUtilities;
24
25 public class PropertyFileDocumentModel {
26
27     private static final char[] HEX_DIGITS = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
28     private List JavaDoc fKeyValuePairs;
29     private String JavaDoc fLineDelimiter;
30
31     public PropertyFileDocumentModel(IDocument document) {
32         parsePropertyDocument(document);
33         fLineDelimiter= TextUtilities.getDefaultLineDelimiter(document);
34     }
35     
36     public int getIndex(String JavaDoc key) {
37         for (int i= 0; i < fKeyValuePairs.size(); i++) {
38             KeyValuePairModell keyValuePair = (KeyValuePairModell) fKeyValuePairs.get(i);
39             if (keyValuePair.getKey().equals(key)) {
40                 return i;
41             }
42         }
43         return -1;
44     }
45     
46
47     public InsertEdit insert(String JavaDoc key, String JavaDoc value) {
48         return insert(new KeyValuePair(key, value));
49     }
50
51     public InsertEdit insert(KeyValuePair keyValuePair) {
52         KeyValuePairModell keyValuePairModell = new KeyValuePairModell(keyValuePair);
53         int index = findInsertPosition(keyValuePairModell);
54         KeyValuePairModell insertHere = (KeyValuePairModell) fKeyValuePairs.get(index);
55         int offset = insertHere.fOffset - insertHere.fLeadingWhiteSpaces;
56         
57         String JavaDoc extra= ""; //$NON-NLS-1$
58
if (insertHere instanceof LastKeyValuePair && ((LastKeyValuePair)insertHere).needsNewLine()) {
59             extra= fLineDelimiter;
60             ((LastKeyValuePair)insertHere).resetNeedsNewLine();
61         }
62         return new InsertEdit(offset, extra + keyValuePairModell.getEncodedText(fLineDelimiter));
63     }
64
65     public InsertEdit[] insert(KeyValuePair[] keyValuePairs) {
66         InsertEdit[] inserts = new InsertEdit[keyValuePairs.length];
67         for (int i = 0; i < keyValuePairs.length; i++) {
68             inserts[i] = insert(keyValuePairs[i]);
69         }
70         return inserts;
71     }
72     
73     public DeleteEdit remove(String JavaDoc key) {
74         for (Iterator JavaDoc iter = fKeyValuePairs.iterator(); iter.hasNext();) {
75             KeyValuePairModell keyValuePair = (KeyValuePairModell) iter.next();
76             if (keyValuePair.fKey.equals(key)) {
77                 KeyValuePairModell next = (KeyValuePairModell) iter.next();
78                 return new DeleteEdit(keyValuePair.fOffset, next.fOffset - keyValuePair.fOffset);
79             }
80         }
81         return null;
82     }
83     
84     public ReplaceEdit replace(KeyValuePair toReplace, KeyValuePair replaceWith) {
85         for (Iterator JavaDoc iter = fKeyValuePairs.iterator(); iter.hasNext();) {
86             KeyValuePairModell keyValuePair = (KeyValuePairModell) iter.next();
87             if (keyValuePair.fKey.equals(toReplace.getKey())) {
88                 String JavaDoc newText = new KeyValuePairModell(replaceWith).getEncodedText(fLineDelimiter);
89                 KeyValuePairModell next = (KeyValuePairModell) iter.next();
90                 int range = next.fOffset - keyValuePair.fOffset;
91                 return new ReplaceEdit(keyValuePair.fOffset, range, newText);
92             }
93         }
94         return null;
95     }
96     
97     private int findInsertPosition(KeyValuePairModell keyValuePair) {
98         int insertIndex = 0;
99         int maxMatch = Integer.MIN_VALUE;
100         for (int i=0; i<fKeyValuePairs.size(); i++) {
101             KeyValuePairModell element = (KeyValuePairModell) fKeyValuePairs.get(i);
102             int match = element.compareTo(keyValuePair);
103             if (match >= maxMatch) {
104                 insertIndex = i;
105                 maxMatch = match;
106             }
107         }
108         
109         if (insertIndex < fKeyValuePairs.size() - 1) {
110             insertIndex++;
111         }
112         
113         return insertIndex;
114     }
115
116     private void parsePropertyDocument(IDocument document) {
117         fKeyValuePairs = new ArrayList JavaDoc();
118       
119         SimpleLineReader reader = new SimpleLineReader(document);
120         int offset = 0;
121         String JavaDoc line = reader.readLine();
122         int leadingWhiteSpaces = 0;
123         while (line != null) {
124             if (!SimpleLineReader.isCommentOrWhiteSpace(line)) {
125                 int idx = getIndexOfSeparationCharacter(line);
126                 if (idx != -1) {
127                     String JavaDoc key= line.substring(0, idx);
128                     String JavaDoc value= line.substring(idx + 1);
129                     fKeyValuePairs.add(new KeyValuePairModell(key, value, offset, leadingWhiteSpaces));
130                     leadingWhiteSpaces = 0;
131                 }
132             } else {
133                 leadingWhiteSpaces += line.length();
134             }
135             offset += line.length();
136             line = reader.readLine();
137         }
138         int lastLine= document.getNumberOfLines() - 1;
139         boolean needsNewLine= false;
140         try {
141             needsNewLine= !(document.getLineLength(lastLine) == 0);
142         } catch (BadLocationException ignore) {
143             // treat last line having no new line
144
}
145         LastKeyValuePair lastKeyValuePair = new LastKeyValuePair(offset, needsNewLine);
146         fKeyValuePairs.add(lastKeyValuePair);
147     }
148     
149     private int getIndexOfSeparationCharacter(String JavaDoc line) {
150         int minIndex = -1;
151         int indexOfEven = line.indexOf('=');
152         int indexOfColumn = line.indexOf(':');
153         int indexOfBlank = line.indexOf(' ');
154         
155         if ((indexOfEven != -1) && (indexOfColumn != -1)) {
156             minIndex = Math.min(indexOfEven, indexOfColumn);
157         } else {
158             minIndex = Math.max(indexOfEven, indexOfColumn);
159         }
160         
161         if ((minIndex != -1) && (indexOfBlank != -1)) {
162             minIndex = Math.min(minIndex, indexOfBlank);
163         } else {
164             minIndex = Math.max(minIndex, indexOfBlank);
165         }
166         
167         return minIndex;
168     }
169     
170     public static String JavaDoc unwindEscapeChars(String JavaDoc s){
171         StringBuffer JavaDoc sb= new StringBuffer JavaDoc(s.length());
172         int length= s.length();
173         for (int i= 0; i < length; i++){
174             char c= s.charAt(i);
175             sb.append(getUnwoundString(c));
176         }
177         return sb.toString();
178     }
179
180     public static String JavaDoc unwindValue(String JavaDoc value) {
181         return escapeLeadingWhiteSpaces(escapeCommentChars(unwindEscapeChars(value)));
182     }
183
184     private static String JavaDoc getUnwoundString(char c){
185                 switch(c){
186                     case '\b' :
187                         return "\\b";//$NON-NLS-1$
188
case '\t' :
189                         return "\\t";//$NON-NLS-1$
190
case '\n' :
191                         return "\\n";//$NON-NLS-1$
192
case '\f' :
193                         return "\\f";//$NON-NLS-1$
194
case '\r' :
195                         return "\\r";//$NON-NLS-1$
196

197 // These can be used unescaped in properties file:
198
// case '\"' :
199
// return "\\\"";//$NON-NLS-1$
200
// case '\'' :
201
// return "\\\'";//$NON-NLS-1$
202

203                     case '\\' :
204                         return "\\\\";//$NON-NLS-1$
205

206 // This is only done when writing to the .properties file in #unwindValue(String)
207
// case '!':
208
// return "\\!";//$NON-NLS-1$
209
// case '#':
210
// return "\\#";//$NON-NLS-1$
211

212                     default:
213                         if (((c < 0x0020) || (c > 0x007e))){
214                             return new StringBuffer JavaDoc()
215                             .append('\\')
216                             .append('u')
217                             .append(toHex((c >> 12) & 0xF))
218                             .append(toHex((c >> 8) & 0xF))
219                             .append(toHex((c >> 4) & 0xF))
220                             .append(toHex( c & 0xF)).toString();
221                             
222                         } else
223                             return String.valueOf(c);
224                 }
225             }
226
227     private static char toHex(int halfByte) {
228         return HEX_DIGITS[(halfByte & 0xF)];
229     }
230
231     private static String JavaDoc escapeCommentChars(String JavaDoc string) {
232         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(string.length() + 5);
233         for (int i = 0; i < string.length(); i++) {
234           char c = string.charAt(i);
235           switch (c) {
236           case '!':
237             sb.append("\\!"); //$NON-NLS-1$
238
break;
239           case '#':
240             sb.append("\\#"); //$NON-NLS-1$
241
break;
242           default:
243             sb.append(c);
244           }
245         }
246         return sb.toString();
247     }
248
249     private static String JavaDoc escapeLeadingWhiteSpaces(String JavaDoc str) {
250         int firstNonWhiteSpace= findFirstNonWhiteSpace(str);
251         StringBuffer JavaDoc buf= new StringBuffer JavaDoc(firstNonWhiteSpace);
252         for (int i = 0; i < firstNonWhiteSpace; i++) {
253             buf.append('\\');
254             buf.append(str.charAt(i));
255         }
256         buf.append(str.substring(firstNonWhiteSpace));
257         return buf.toString();
258     }
259
260     /**
261      * returns the length if only whitespaces
262      */

263     private static int findFirstNonWhiteSpace(String JavaDoc s) {
264         for (int i = 0; i < s.length(); i++) {
265             if (!Character.isWhitespace(s.charAt(i)))
266                 return i;
267         }
268         return s.length();
269     }
270
271     private static class KeyValuePairModell extends KeyValuePair implements Comparable JavaDoc {
272
273         int fOffset;
274         int fLeadingWhiteSpaces;
275
276         public KeyValuePairModell(String JavaDoc key, String JavaDoc value, int offset, int leadingWhiteSpaces) {
277             super(key, value);
278             fOffset = offset;
279             fLeadingWhiteSpaces = leadingWhiteSpaces;
280         }
281         
282         public KeyValuePairModell(KeyValuePair keyValuePair) {
283             super(keyValuePair.fKey, keyValuePair.fValue);
284         }
285
286         public String JavaDoc getEncodedText(String JavaDoc lineDelimiter) {
287             return PropertyFileDocumentModel.unwindEscapeChars(fKey) + '=' + PropertyFileDocumentModel.unwindValue(fValue) + lineDelimiter;
288         }
289         
290         public int compareTo(Object JavaDoc o) {
291             int counter = 0;
292             String JavaDoc key = ((KeyValuePair) o).fKey;
293             int minLen = Math.min(key.length(), fKey.length());
294             int diffLen = Math.abs(key.length() - fKey.length());
295             for (int i=0; i<minLen; i++) {
296                 if (key.charAt(i) == fKey.charAt(i)) {
297                     counter++;
298                 } else {
299                     break;
300                 }
301             }
302             return counter - diffLen;
303         }
304     }
305
306     /**
307      * anchor element for a list of KeyValuePairs. (it is greater than every
308      * other KeyValuePair)
309      */

310     private static class LastKeyValuePair extends KeyValuePairModell {
311
312         private boolean fNeedsNewLine;
313         
314         public LastKeyValuePair(int offset, boolean needsNewLine) {
315             super("last", "key", offset, 0); //$NON-NLS-1$ //$NON-NLS-2$
316
fNeedsNewLine= needsNewLine;
317         }
318         public int compareTo(Object JavaDoc o) {
319             return 1;
320         }
321         public boolean needsNewLine() {
322             return fNeedsNewLine;
323         }
324         public void resetNeedsNewLine() {
325             fNeedsNewLine= false;
326         }
327     }
328 }
329
Popular Tags