Révision 1407

tmp/org.txm.translate.rcp/src/org/txm/rcp/translate/i18n/PluginMessagesManager.java (revision 1407)
131 131
	/**
132 132
	 * 
133 133
	 * @param projectDirectory
134
	 * @param javaMessageFile
134
	 * @param javaPreferenceFile
135 135
	 * @throws UnsupportedEncodingException
136 136
	 * @throws FileNotFoundException
137 137
	 * @throws IOException
tmp/org.txm.translate.rcp/src/org/txm/rcp/translate/preferences/PluginPreferencesManager.java (revision 1407)
1
package org.txm.rcp.translate.preferences;
2

  
3
import java.io.BufferedReader;
4
import java.io.File;
5
import java.io.FileInputStream;
6
import java.io.FileNotFoundException;
7
import java.io.IOException;
8
import java.io.InputStreamReader;
9
import java.io.PrintWriter;
10
import java.io.UnsupportedEncodingException;
11
import java.text.Collator;
12
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.Enumeration;
17
import java.util.HashMap;
18
import java.util.Locale;
19
import java.util.Map;
20
import java.util.Properties;
21
import java.util.TreeMap;
22
import java.util.TreeSet;
23
import java.util.regex.Matcher;
24
import java.util.regex.Pattern;
25

  
26
import org.apache.commons.io.FilenameUtils;
27
import org.apache.commons.lang.StringUtils;
28
import org.txm.rcp.translate.devtools.NormalizeKeys;
29
import org.txm.utils.BiHashMap;
30
import org.txm.utils.io.IOUtils;
31

  
32
/**
33
 *  
34
 * Check any missing key in both of messages.properties and Preference.java files
35
 *
36
 * @author mdecorde
37
 * @author sjacquot
38
 *
39
 */
40
public class PluginPreferencesManager {
41
	/**
42
	 * Files encoding.
43
	 */
44
	public static String ENCODING = "UTF-8";
45

  
46
	public final static String FILE_SEPARATOR = System.getProperty("file.separator");
47

  
48
	/**
49
	 * Debug state.
50
	 */
51
	protected boolean debug;
52

  
53
	/**
54
	 * Project root directory.
55
	 */
56
	protected File projectDirectory;
57

  
58
	/**
59
	 * Java message file, eg.: TXMCorePreferences.java, ConcordanceUIPreferences.java, etc.
60
	 */
61
	protected File javaPreferenceFile;
62

  
63
	/**
64
	 * Source files of the project.
65
	 */
66
	protected ArrayList<File> srcFiles;
67

  
68
	/**
69
	 * Extensions to use when creating the source files list.
70
	 */
71
	protected static final String[] srcFilesExtensions = new String[] {"java", "groovy"};
72

  
73
	/**
74
	 * Index of the keys used and their associated files.
75
	 */
76
	protected TreeMap<String, TreeSet<File>> usedKeysFilesIndex = new TreeMap<String, TreeSet<File>>();
77

  
78
	/**
79
	 * the XXXPreferences.java preferences keys
80
	 */
81
	TreeSet<String> preferenceKeys = new TreeSet<String>();
82
	
83
	protected TreeMap<String, Object> names = new TreeMap<String, Object>();
84
	
85
	protected TreeMap<String, Object> defaultValues = new TreeMap<String, Object>();
86

  
87
	/**
88
	 * plugin.xml file -> contains eventually keys
89
	 */
90
	protected File pluginXMLFile;
91

  
92
	public File getPluginXMLFile() {
93
		return pluginXMLFile;
94
	}
95

  
96
	/**
97
	 * Stores the key modifications for further saves in the source files
98
	 */
99
	HashMap<String, String> keyModifications = new HashMap<String, String>();
100

  
101
	/**
102
	 * the properties files langs
103
	 */
104
	BiHashMap<File, String> file2lang = new BiHashMap<File, String>();
105

  
106
	/**
107
	 * 
108
	 * @param projectDirectory
109
	 * @param javaPreferenceFile
110
	 * @throws UnsupportedEncodingException
111
	 * @throws FileNotFoundException
112
	 * @throws IOException
113
	 */
114
	public PluginPreferencesManager(File projectDirectory) throws UnsupportedEncodingException, FileNotFoundException, IOException {
115
		this(projectDirectory, false);
116
	}
117

  
118
	/**
119
	 * 
120
	 * @param projectDirectory
121
	 * @param debug
122
	 * @throws UnsupportedEncodingException
123
	 * @throws FileNotFoundException
124
	 * @throws IOException
125
	 */
126
	public PluginPreferencesManager(File projectDirectory, boolean debug) throws UnsupportedEncodingException, FileNotFoundException, IOException {
127
		this(projectDirectory, findPreferenceFile(projectDirectory), debug);
128
	}
129

  
130

  
131

  
132
	/**
133
	 * 
134
	 * @param projectDirectory
135
	 * @param javaPreferenceFile
136
	 * @throws UnsupportedEncodingException
137
	 * @throws FileNotFoundException
138
	 * @throws IOException
139
	 */
140
	public PluginPreferencesManager(File projectDirectory, File javaPreferenceFile) throws UnsupportedEncodingException, FileNotFoundException, IOException {
141
		this(projectDirectory, javaPreferenceFile, false);
142
	}
143

  
144

  
145

  
146
	/**
147
	 * 
148
	 * @param projectDirectory
149
	 * @param javaPreferenceFile
150
	 * @throws UnsupportedEncodingException
151
	 * @throws FileNotFoundException
152
	 * @throws IOException
153
	 */
154
	public PluginPreferencesManager(File projectDirectory, File javaPreferenceFile, boolean debug) throws UnsupportedEncodingException, FileNotFoundException, IOException {
155

  
156
		this.javaPreferenceFile = javaPreferenceFile;
157
		this.projectDirectory = projectDirectory;
158
		this.pluginXMLFile = new File(projectDirectory, "plugin.xml");
159
		this.srcFiles = new ArrayList<File>();
160
		this.debug = debug;
161

  
162
		if (debug) {
163
			System.out.println("********************************************************************************************************************");
164
			System.out.println("PluginPreferencesManager.PluginPreferences(): project root directory = " + this.projectDirectory);
165
			System.out.println("PluginPreferencesManager.PluginPreferences(): java message file = " + this.javaPreferenceFile);
166
		}
167

  
168
		// create the project source files list
169
		this.createSourceFilesList();
170

  
171
		//this.createKeysGlobalREGEX();
172
		this.createUsedKeysFilesIndex();
173

  
174

  
175
		if (this.javaPreferenceFile != null) {
176
			String className = getPreferenceClassName();
177
			
178
			BufferedReader reader2 = new BufferedReader(new InputStreamReader(new FileInputStream(javaPreferenceFile), ENCODING));
179
			String line2 = reader2.readLine();
180
			while (line2 != null) {
181
				line2 = line2.trim();
182

  
183
				if (line2.startsWith("public static final String")) {
184
					int idx = line2.indexOf("//");
185
					if (idx > 0 && line2.contains("\"")) { // remove comment from line
186
						//System.out.println("COMMENT DETECTED AFTER KEY: line="+line2+" IN "+javaPreferenceFile);
187
						line2 = line2.substring(0, idx).trim();
188
					}
189
					if (line2.endsWith(";") && line2.contains("=") && line2.contains("\"")) {
190
						String key = line2.substring(27, line2.indexOf("=") -1);
191
						String name = line2.substring(line2.indexOf("\"")+1, line2.indexOf("\";"));
192

  
193
						if(debug)	{
194
							System.out.println("PluginPreferencesManager.PluginPreferencesManager(): messages key: " + line2 + " added.");
195
						}
196
						//System.out.println("+K='"+key+"'");
197
						preferenceKeys.add(key);
198
						names.put(key, name);
199
					}
200
				} else if (line2.startsWith("preferences.put")) {
201
					int idx = line2.indexOf("//");
202
					if (idx > 0 && line2.contains("\"")) { // remove comment from line
203
						//System.out.println("COMMENT DETECTED AFTER KEY: line="+line2+" IN "+javaPreferenceFile);
204
						line2 = line2.substring(0, idx).trim();
205
					}
206
//					System.out.println(line2);
207
//					System.out.println(""+line2.indexOf("preferences.put")+" "+line2.indexOf("(")+" "+line2.indexOf(", ")+ " "+line2.indexOf(");"));
208
					if (line2.indexOf("preferences.put") < line2.indexOf("(") && 
209
							line2.indexOf("(") < line2.indexOf(", ") && 
210
							line2.indexOf(", ") < line2.indexOf(");")) {
211
						
212
						String key = line2.substring(line2.indexOf("(")+1, line2.indexOf(", "));
213
						String value = line2.substring(line2.indexOf(", ")+2, line2.indexOf(");"));
214
						//System.out.println("K2='"+key+"' V='"+value+"'");
215
						if(debug)	{
216
							System.out.println("PluginPreferencesManager.PluginPreferencesManager(): messages key: " + line2 + " added.");
217
						}
218
						defaultValues.put(key, value);
219
					}
220
				}
221

  
222
				line2 = reader2.readLine();
223
			}
224
			reader2.close();
225

  
226

  
227
			if(debug)	{
228
				System.out.println("PluginPreferencesManager.PluginPreferencesManager(): number of keys: " + this.preferenceKeys.size() + ".");
229
			}
230

  
231
			if(debug)	{
232
				this.dumpUsedKeysFilesIndex();
233
			}
234
		}
235
		else {
236
			if (debug) {
237
				System.err.println("PluginPreferencesManager.PluginPreferencesManager(): skipped, java message file not found for project " + this.projectDirectory + ".");
238
			}
239
		}
240
	}
241

  
242
	//		/**
243
	//		 * Creates a global REGEX containing all keys to later search in files.
244
	//		 */
245
	//		public void createKeysGlobalREGEX()	{
246
	//			
247
	//			if(messageKeys.size() == 0) {
248
	//				return;
249
	//			}
250
	//			
251
	//			StringBuffer buffer = new StringBuffer();
252
	//			buffer.append(this.getPreferenceClassName() + "\\\\.(");
253
	//			
254
	//			int i = 0;
255
	//			for (String key : messageKeys) {
256
	//				if(i > 0)	{
257
	//					buffer.append("|" + key);	
258
	//				}
259
	//				else {
260
	//					buffer.append(key);
261
	//				}
262
	//				i++;
263
	//			}
264
	//			
265
	//			// remove first pipe
266
	//			//buffer.deleteCharAt(0);
267
	//			
268
	//			this.keysGlobalREGEX = Pattern.compile("(" + buffer + "))");
269
	//			
270
	//			if(debug)	{
271
	//				System.out.println("PluginPreferencesManager.createKeysGlobalREGEX(): REGEX created: " + this.keysGlobalREGEX + ".");
272
	//			}
273
	//			
274
	//		}
275

  
276
	public static File findPreferenceFile(File projectDirectory2) {
277
		File messagesPackageDir = new File(projectDirectory2, "src/"+projectDirectory2.getName().replaceAll("\\.", "/")+"/preferences");
278

  
279
		if (!messagesPackageDir.exists()) {
280
			messagesPackageDir = new File(projectDirectory2, "src/java/"+projectDirectory2.getName().replaceAll("\\.", "/")+"/preferences");
281
		}
282

  
283
		if (!messagesPackageDir.exists()) {
284
			messagesPackageDir = new File(projectDirectory2, "src/main/java/"+projectDirectory2.getName().replaceAll("\\.", "/")+"/preferences");
285
		}
286

  
287
		if (!messagesPackageDir.exists()) {
288
			return null;
289
		}
290

  
291
		for (File messagesJavaFile : messagesPackageDir.listFiles(IOUtils.FILTER_HIDDEN)) {
292
			if (messagesJavaFile.isDirectory()) continue;
293
			if (!messagesJavaFile.getName().endsWith("Preferences.java")) continue;
294
			return messagesJavaFile;
295
		}
296
		return null;
297
	}
298

  
299
	/**
300
	 * Creates/updates the index of the keys used and their associated files.
301
	 * @throws IOException 
302
	 */
303
	public void createUsedKeysFilesIndex() throws IOException	{
304
		this.usedKeysFilesIndex = new TreeMap<String, TreeSet<File>>();
305

  
306
		// New version using REGEX
307
		for (File file : this.srcFiles) {
308
			if (!file.exists()) continue;
309
			String lines = IOUtils.getText(file, PluginPreferencesManager.ENCODING);
310

  
311
			Matcher m = WorkspacePreferencesManager.KEY_REGEX.matcher(lines);
312
			//Matcher m = this.keysGlobalREGEX.matcher(lines);
313
			while (m.find()) {
314
				// Get the matching string
315
				String key = m.group();
316

  
317
				if (!this.usedKeysFilesIndex.containsKey(key)) {
318
					this.usedKeysFilesIndex.put(key, new TreeSet<File>());
319
				}
320
				this.usedKeysFilesIndex.get(key).add(file);
321

  
322
				if(debug) {
323
					System.out.println("PluginPreferencesManager.createUsedKeysFilesIndex(): messages key: " + key + " added for file " + file +  ".");
324
				}
325
			}
326
		}
327
	}
328

  
329

  
330
	/**
331
	 * Dumps in console the index of the keys used and their associated files.
332
	 */
333
	public void dumpUsedKeysFilesIndex()	{
334

  
335
		System.out.println("PluginPreferencesManager.dumpUsedKeysIndex(): dumping used keys files index...");
336

  
337
		if(this.usedKeysFilesIndex == null)	{
338
			System.out.println("PluginPreferencesManager.dumpUsedKeysIndex(): project have no used keys.");
339
			return;
340
		}
341

  
342
		for (Map.Entry<String, TreeSet<File>> entry : this.usedKeysFilesIndex.entrySet()) {
343
			System.out.println("key: " + entry.getKey());
344
			if(entry.getValue().isEmpty())	{
345
				System.out.println("   file(s): -not used in any file of the project " + this.getProjectDirectory() + "-");
346
			}
347
			else	{
348
				for(File file : entry.getValue())	{
349
					System.out.println("   file(s): " + file);
350
				}
351
			}
352
		}
353

  
354
		System.out.println("PluginPreferencesManager.dumpUsedKeysIndex(): number of used keys: " + this.usedKeysFilesIndex.size() + ".");
355
	}
356

  
357
	/***
358
	 * @param key
359
	 * @return all source files using the specified message key (except the main Java message file).
360
	 */
361
	public TreeSet<File> getFilesUsingKey(String key) {
362
		if (usedKeysFilesIndex.containsKey(key)) {
363
			return this.usedKeysFilesIndex.get(key);
364
		} else {
365
			return new TreeSet<File>();
366
		}
367
	}
368

  
369
	/***
370
	 * @param key local key name
371
	 * @return all source files using the specified local message key (except the main Java message file).
372
	 */
373
	public TreeSet<File> getFilesUsingLocalKey(String key) {
374
		return getFilesUsingKey(getKeyFullName(key));
375
	}
376

  
377

  
378
	/**
379
	 * Returns the keys of all messages that are not used in the project itself.
380
	 * @return a sorted list containing all unused keys
381
	 */
382
	public ArrayList<String> getUnusedKeys()	{
383
		return getUnusedKeys(usedKeysFilesIndex, debug);
384
	}
385

  
386
	/**
387
	 * @param usedKeysFilesIndex
388
	 * 
389
	 * @return a sorted list containing all unused keys of all messages that are not used in the used key files index.
390
	 */
391
	public static ArrayList<String> getUnusedKeys(TreeMap<String, TreeSet<File>> usedKeysFilesIndex, boolean debug)	{
392
		ArrayList<String> unusedKeys = new ArrayList<String>();
393
		for (Map.Entry<String, TreeSet<File>> entry : usedKeysFilesIndex.entrySet()) {
394
			if(entry.getValue().isEmpty())	{
395

  
396
				if(debug)	{
397
					System.out.println("PluginPreferencesManager.getUnusedKeys(): unused key found: " + entry.getKey() + ".");
398
				}
399

  
400
				unusedKeys.add(entry.getKey());
401
			}
402
		}
403

  
404
		Collections.sort(unusedKeys);
405
		return unusedKeys;
406
	}
407

  
408
	public void put(String key, String defaultValue) {
409
		preferenceKeys.add(key);
410
		defaultValues.put(key, defaultValue);
411
	}
412

  
413
	public Object getDefaultValue(String key) {
414
		return defaultValues.get(key);
415
	}
416

  
417
	public TreeSet<String> getPreferenceKeys() {
418
		return preferenceKeys;
419
	}
420

  
421
	public File getPreferenceFile() {
422
		return javaPreferenceFile;
423
	}
424

  
425
	public String getPreferenceClassName() {
426
		if (javaPreferenceFile == null) return "";
427
		return javaPreferenceFile.getName().substring(0, javaPreferenceFile.getName().length() - 5);
428
	}
429

  
430
	public String getPreferenceFullClassName() {
431
		if (javaPreferenceFile == null) return "";
432
		return javaPreferenceFile.getAbsolutePath().substring(javaPreferenceFile.getAbsolutePath().lastIndexOf("org" + FILE_SEPARATOR + "txm" + FILE_SEPARATOR),
433
				javaPreferenceFile.getAbsolutePath().length() - 5).replace(FILE_SEPARATOR, ".");
434
	}
435

  
436
	/**
437
	 * @return the XXXPreferences.java class name without the 'Preferences' part
438
	 */
439
	public String getPreferenceName() {
440
		if (javaPreferenceFile == null) return "";
441
		return javaPreferenceFile.getName().substring(0, javaPreferenceFile.getName().length()-5-8);
442
	}
443

  
444
	public String getPreferenceFullName() {
445
		if (javaPreferenceFile == null) return "";
446
		return javaPreferenceFile.getAbsolutePath().substring(javaPreferenceFile.getAbsolutePath().lastIndexOf("org" + FILE_SEPARATOR + "txm" + FILE_SEPARATOR) + 8, 
447
				javaPreferenceFile.getAbsolutePath().length() - 5 - 8).replace(FILE_SEPARATOR, ".");
448
	}
449

  
450
	/**
451
	 * Returns the full name of the specified key including the Java message class name.
452
	 * @param key
453
	 * @return
454
	 */
455
	public String getKeyFullName(String key)	{
456
		return this.getPreferenceClassName() + "." + key;
457
	}
458

  
459
	public static Collator col = Collator.getInstance(Locale.FRANCE);
460
	public static Comparator comp = new Comparator<String>() {
461
		@Override
462
		public int compare(String arg0, String arg1) {
463
			return col.compare(arg0, arg1);
464
		}
465
	};
466
	static {
467
		col.setStrength(Collator.TERTIARY);
468
	}
469
	public void saveChanges(boolean replaceFiles) throws IOException {
470

  
471
		if (javaPreferenceFile == null) return;
472

  
473
		// write message File
474
		File newJavaPreferenceFile = new File(javaPreferenceFile.getParentFile(), javaPreferenceFile.getName()+".new");
475

  
476
//		ArrayList<String> lines = IOUtils.getLines(javaPreferenceFile, "UFT-8");
477
//		TreeSet<String> oldKeys = new TreeSet<String>(IOUtils.findWithGroup(javaPreferenceFile, "public static String ([^\"=;]+);"));
478
//		TreeSet<String> newKeys = new TreeSet<String>(preferenceKeys);
479
//		TreeSet<String> writtenKeys = new TreeSet<String>();
480
//		
481
//		newKeys.removeAll(oldKeys);
482
//		newKeys.removeAll(keyModifications.values()); // now contains only the very newly created keys
483
//
484
//		if (replaceFiles) {
485
//			newJavaPreferenceFile = javaPreferenceFile;
486
//		}
487
//
488
//		PrintWriter out = IOUtils.getWriter(newJavaPreferenceFile, ENCODING);
489
//
490
//		// update lines
491
//		for (String line : lines) {
492
//			String l = line.trim();// remove tabs
493
//			String comments = "";
494
//			int idx = l.indexOf("//"); // remove comments
495
//			if (idx > 0) {
496
//				comments = l.substring(idx).trim();
497
//				l = l.substring(0, idx).trim();
498
//			}
499
//
500
//			if (l.startsWith("private static final String BUNDLE_NAME")) {
501
//				out.println(line);
502
//
503
//				// write the totally new keys
504
//				if (newKeys.size() > 0) {
505
//					out.println("\t");
506
//				}
507
//				for (String key : newKeys) {
508
//					if (writtenKeys.contains(key)) continue; // key already written
509
//					out.println("\tpublic static String "+key+";");
510
//					writtenKeys.add(key);
511
//				}
512
//			} else if (l.startsWith("public static String") && l.endsWith(";") && !l.contains("=") && !l.contains("\"")) {
513
//
514
//				String key = l.substring(21, l.length() -1);
515
//				if (preferenceKeys.contains(key)) {
516
//					if (writtenKeys.contains(key)) continue; // key already written
517
//					out.println(line); // keep the line
518
//					writtenKeys.add(key);
519
//				} else if (keyModifications.containsKey(key)){
520
//					// the key has been renamed
521
//					if (writtenKeys.contains(keyModifications.get(key))) continue; // key already written
522
//					out.println("\tpublic static String "+keyModifications.get(key)+"; "+comments);
523
//					writtenKeys.add(keyModifications.get(key));
524
//				} else {
525
//					// the key has been removed
526
//				}
527
//			} else {
528
//				out.println(line);
529
//			}
530
//		}
531
//
532
//		out.close();
533
	}
534

  
535
	public void summary() {
536
		String name = getPreferenceClassName();
537
		if (name == null || name.length() == 0) return;
538
		System.out.println(name+" "+preferenceKeys.size()+" preferences");
539
//		System.out.println(preferenceKeys);
540
//		System.out.println(names);
541
//		System.out.println(defaultValues);
542
		for (String key : preferenceKeys) {
543
			System.out.println(key+"\t"+names.get(key)+"\t"+defaultValues.get(key));
544
		}
545
	}
546

  
547
	/**
548
	 * Parses the specified path and stores a list of the source files. 
549
	 */
550
	private void createSourceFilesList(File path)	{
551
		File[] list = path.listFiles(IOUtils.FILTER_HIDDEN);
552

  
553
		if (list == null) {
554
			return;
555
		}
556

  
557
		for (File file : list) {
558
			if (file.isDirectory()) {
559
				this.createSourceFilesList(file);
560
			}
561
			else if (!file.equals(this.javaPreferenceFile)
562
					&& Arrays.asList(this.srcFilesExtensions).contains(FilenameUtils.getExtension(file.getName())) 
563
					) {
564

  
565
				if (debug) {
566
					System.out.println("PluginPreferencesManager.createSourceFilesList(): adding source files " + file + ".");
567
				}
568
				else	{
569
					//System.out.print(".");
570
				}
571

  
572
				this.srcFiles.add(file);
573
			}
574
		}
575
	}
576

  
577
	/**
578
	 * Parses the project and stores a list of the source files.
579
	 */
580
	public void createSourceFilesList()	{
581

  
582
		if (debug) {
583
			System.out.println("PluginPreferencesManager.loadSourceFilesList(): creating source files list for extensions [" + StringUtils.join(this.srcFilesExtensions, ", ") + "]...");
584
		}
585

  
586
		this.createSourceFilesList(this.projectDirectory);
587

  
588

  
589
		if(debug) {
590
			System.out.println("PluginPreferencesManager.loadSourceFilesList(): done. Source files count = " + this.srcFiles.size() + ".");
591
		}
592
	}
593

  
594
	/**
595
	 * Rename a key and update in the properties file the keys
596
	 * 
597
	 * stores the modification to rename the keys later in the Workspace source files
598
	 * 
599
	 * @param oldName
600
	 * @param newName
601
	 */
602
	public void renameKey(String oldName, String newName) {
603

  
604
		if (!preferenceKeys.contains(oldName)) {
605
			System.err.println("PluginPreferencesManager.renameKey(): key=" + oldName + " not found, aborting renaming to " + newName + ".");
606
			return;
607
		}
608

  
609
		// continue only if key name has changed
610
		if(oldName.equals(newName))	{
611
			if(debug)	{
612
				System.out.println("PluginPreferencesManager.renameKey(): no changes, skipped key: " + oldName + " = " + newName);
613
			}
614
			return;
615
		}
616

  
617
		preferenceKeys.remove(oldName);
618
		preferenceKeys.add(newName);
619

  
620
		defaultValues.put(newName, defaultValues.get(oldName));
621
		defaultValues.remove(oldName);
622

  
623
		//System.out.println("M+ "+oldName+" -> "+newName);
624
		keyModifications.put(oldName, newName);
625
	}
626

  
627
	/**
628
	 * Remove a messages from XXPreferences.java and messages.properties files
629
	 * 
630
	 * @param key the local name of the key to remove
631
	 */
632
	public void removeKey(String key) {
633
		if (!preferenceKeys.contains(key)) {
634
			System.err.println("PluginPreferencesManager.removeKey(): key=" + key + " not found, aborting removing.");
635
			return;
636
		}
637

  
638
		preferenceKeys.remove(key);
639
		defaultValues.remove(key);
640

  
641
		keyModifications.remove(key); // if any modifications was done
642
	}
643

  
644
	public void newKey(String defaultPreference) {
645
		String key = NormalizeKeys.normalize(defaultPreference);
646
		String newKey = ""+key;
647
		int c = 1;
648
		while (preferenceKeys.contains(newKey)) {
649
			newKey = key+"_"+(c++);
650
		}
651

  
652
		preferenceKeys.add(newKey);
653
	}
654

  
655
	/**
656
	 * 
657
	 * @return the renamed keys
658
	 */
659
	public HashMap<String, String> getKeyModifications() {
660
		return keyModifications;
661
	}
662

  
663
	public BiHashMap<File, String> getFile2lang() {
664
		return file2lang;
665
	}
666

  
667
	public TreeMap<String, Object> getDefaults() {
668
		return defaultValues;
669
	}
670

  
671
	/**
672
	 * Gets the project root directory.
673
	 * @return the projectDirectory
674
	 */
675

  
676
	public File getProjectDirectory() {
677
		return projectDirectory;
678
	}
679

  
680

  
681
	/**
682
	 * Dumps the specified BiHashMap<String, String> to standard output.
683
	 */
684
	public void dump(BiHashMap<String, String> messages)	{
685
		for (String key : messages.getKeys()) {
686
			System.out.println("PluginPreferencesManager.dump(): " + key + "=" + messages.get(key));
687
		}
688
	}
689

  
690

  
691
	/**
692
	 * Dumps the keys replacements table.
693
	 */
694
	public void dumpKeysReplacements()	{
695
		System.out.println("PluginPreferencesManager.dumpKeysReplacements(): keys replacements table");
696
		for (String key : this.keyModifications.keySet()) {
697
			System.out.println("PluginPreferencesManager.dumpKeysReplacements(): " + key + "=>" + this.keyModifications.get(key));
698
		}
699
	}
700

  
701
	/**
702
	 * @return the usedKeysIndex
703
	 */
704
	public TreeMap<String, TreeSet<File>> getUsedKeysFilesIndex() {
705
		return usedKeysFilesIndex;
706
	}
707

  
708
	/**
709
	 * 
710
	 * @param args
711
	 * @throws UnsupportedEncodingException
712
	 * @throws FileNotFoundException
713
	 * @throws IOException
714
	 */
715
	public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException, IOException {
716

  
717
		long startTime = System.currentTimeMillis();
718

  
719
		//File projectFile = new File(new File(System.getProperty("user.dir")).getParentFile().getAbsolutePath() + "/org.txm.rcp");
720
		File projectFile = new File(new File(System.getProperty("user.dir")).getParentFile().getAbsolutePath() + "/org.txm.core");
721

  
722
		PluginPreferencesManager pmManager = new PluginPreferencesManager(projectFile, true);
723

  
724
		// test to find files using the specified key
725
		/*
726
		String key = "TXMCorePreferences.binaryDirectory";
727
		TreeSet<File> files = pmManager.getFilesUsingKey(key);
728
		System.out.println("getFilesUsingKey: files using key: " + key);
729
		for(File file : files)	{
730
			System.out.println("   file: " + file);
731
		}
732
		key = "TXMCorePreferences.common_frequency";
733
		files = pmManager.getFilesUsingKey(key);
734
		System.out.println("getFilesUsingKey: files using key: " + key);
735
		for(File file : files)	{
736
			System.out.println("   file: " + file);
737
		}
738

  
739
		// test to find unused keys
740
		ArrayList<String> unusedKeys = pmManager.getUnusedKeys();
741
		for (int i = 0; i < unusedKeys.size(); i++) {
742
			System.out.println("findUnusedKeys: key " + unusedKeys.get(i) + " is unused in project " + pmManager.getProjectDirectory() + " (main language value = " + pmManager.getPreferencesForLang("").get(unusedKeys.get(i)) + ")");	
743
		}
744
		 */
745
		//dict.summary();
746

  
747
		pmManager.saveChanges(false);
748

  
749
		System.out.println("dir="+pmManager.getProjectDirectory());
750
		System.out.println("Elapsed time:"+ ((double)(System.currentTimeMillis()-startTime)/1000));
751

  
752
		System.out.println("PluginPreferencesManager.main(): done.");
753
	}
754
}
0 755

  
tmp/org.txm.translate.rcp/src/org/txm/rcp/translate/preferences/WorkspacePreferencesManager.java (revision 1407)
1
package org.txm.rcp.translate.preferences;
2

  
3
import java.io.File;
4
import java.io.FileNotFoundException;
5
import java.io.IOException;
6
import java.io.UnsupportedEncodingException;
7
import java.util.ArrayList;
8
import java.util.Collections;
9
import java.util.Comparator;
10
import java.util.HashMap;
11
import java.util.LinkedHashMap;
12
import java.util.Map;
13
import java.util.TreeMap;
14
import java.util.TreeSet;
15
import java.util.regex.Pattern;
16

  
17
import org.txm.stat.utils.ConsoleProgressBar;
18
import org.txm.utils.io.IOUtils;
19

  
20
/**
21
 * Manages the messages of the TXM projects of an RCP workspace
22
 * 
23
 * @author mdecorde
24
 *
25
 */
26
public class WorkspacePreferencesManager {
27

  
28
	/**
29
	 * Debug state.
30
	 */
31
	protected boolean debug = false;
32

  
33
	/**
34
	 * the plugins discovered and their messages
35
	 */
36
	LinkedHashMap<File, PluginPreferencesManager> pluginsPreferencesPerProject = new LinkedHashMap<File, PluginPreferencesManager>();
37

  
38
	/**
39
	 * the Eclipse RCP workspace location containing the projects
40
	 */
41
	File workspaceLocation;
42

  
43
	/**
44
	 * Index of the keys used in all plugins sources files.
45
	 */
46
	protected TreeMap<String, TreeSet<File>> usedKeysFilesIndex;
47

  
48
	/**
49
	 * Generic Regex to find keys in source files 
50
	 */
51
	public static final Pattern KEY_REGEX = Pattern.compile("(?:[A-Z][a-zA-Z0-9]+)?Preferences\\.[a-zA-Z0-9_]+");
52

  
53
	/**
54
	 * Generic Regex to find Strings in source files. Warning the "\"" strings are not found. 
55
	 */
56
	public static final Pattern STRING_REGEX = Pattern.compile("\"[^\"]+\"");
57

  
58
	/**
59
	 * 
60
	 * @throws UnsupportedEncodingException
61
	 * @throws FileNotFoundException
62
	 * @throws IOException
63
	 */
64
	public WorkspacePreferencesManager() throws UnsupportedEncodingException, FileNotFoundException, IOException {
65
		this(false);
66
	}
67

  
68
	/**
69
	 * Creates the manager using the "user.dir" parent directory -> works when run from Eclipse
70
	 * 
71
	 * @throws IOException 
72
	 * @throws FileNotFoundException 
73
	 * @throws UnsupportedEncodingException 
74
	 */
75
	public WorkspacePreferencesManager(boolean debug) throws UnsupportedEncodingException, FileNotFoundException, IOException {
76
		this(new File(System.getProperty("user.dir")).getParentFile(), debug);
77
	}
78

  
79
	/**
80
	 * Build a WorkspacePreferencesManager for a certain workspace directory
81
	 * 
82
	 * @param workspaceLocation
83
	 * @throws UnsupportedEncodingException
84
	 * @throws FileNotFoundException
85
	 * @throws IOException
86
	 */
87
	public WorkspacePreferencesManager(File workspaceLocation, boolean debug) throws UnsupportedEncodingException, FileNotFoundException, IOException {
88

  
89
		if (!new File(workspaceLocation, ".metadata").exists()) {
90
			throw new IllegalArgumentException("Workspace directory is not a RCP workspace: "+workspaceLocation);
91
		}
92

  
93
		this.workspaceLocation = workspaceLocation;
94
		this.debug = debug;
95

  
96
		if (debug) {
97
			System.out.println("WorkspacePreferencesManager.WorkspacePreferencesManager(): workspace location = " + this.workspaceLocation);
98
		}
99

  
100
		if (!workspaceLocation.exists()) return;
101
		if (!workspaceLocation.isDirectory()) {
102
			System.out.println("Error: workspace not found in: "+workspaceLocation);
103
			return;
104
		}
105

  
106
		System.out.println("Initializing project preferences...");
107
		ArrayList<File> files = new ArrayList<File>();
108
		for (File project : workspaceLocation.listFiles(IOUtils.FILTER_HIDDEN)) {
109
			if (!project.isDirectory()) continue;
110
			if (project.isHidden()) continue;
111
			if (!project.getName().startsWith("org.txm")) continue;
112
			if (project.getName().endsWith(".feature")) continue;
113
			files.add(project);
114
		}
115
		ConsoleProgressBar cpb = new ConsoleProgressBar(files.size());
116
		for (File project : files) {
117
			cpb.tick();
118

  
119
			//			File messagesPackageDir = new File(project, "src/"+project.getName().replaceAll("\\.", "/")+"/messages");
120
			//			if (!messagesPackageDir.exists()) {
121
			//				messagesPackageDir = new File(project, "src/java/"+project.getName().replaceAll("\\.", "/")+"/messages");
122
			//			}
123
			//			//System.out.println(messagesPackageDir.getAbsolutePath());
124
			//
125
			//			File messagesJavaFile = PluginPreferences.findPreferenceFile(project);
126

  
127
			//			if (messagesJavaFile != null && messagesJavaFile.exists()) {
128

  
129
			PluginPreferencesManager preferences = new PluginPreferencesManager(project, debug);
130

  
131
			pluginsPreferencesPerProject.put(project, preferences);
132

  
133
			if (debug) {
134
				System.out.println(project + "=" + preferences.getPreferenceKeys().size() + " preferences and "+preferences.getDefaults().size()+" default values.");
135
			}
136
			//			}
137
		}
138
		cpb.done();
139

  
140
		this.createUsedKeysFilesIndex();
141

  
142
		// Log summary
143
		if (debug) {
144

  
145
			this.dumpUsedKeysFilesIndex();
146

  
147
			System.out.println("WorkspacePreferencesManager.WorkspacePreferencesManager(): ------------------ process summary --------------------------------------------------------------");
148
			System.out.println("WorkspacePreferencesManager.WorkspacePreferencesManager(): numbers of projects: " + this.pluginsPreferencesPerProject.size() + ".");
149
			System.out.println("WorkspacePreferencesManager.WorkspacePreferencesManager(): numbers of used keys: " + this.usedKeysFilesIndex.size() + ".");
150
			System.out.println("WorkspacePreferencesManager.WorkspacePreferencesManager(): done.");
151
		}
152
	}
153

  
154
	public TreeMap<String, TreeSet<File>> getUsedKeysFilesIndex() {
155
		return usedKeysFilesIndex;
156
	}
157

  
158
	/**
159
	 *  Dumps the index of the keys used and their associated files.
160
	 */
161
	protected void dumpUsedKeysFilesIndex() {
162
		System.out.println("WorkspacePreferencesManager.dumpUsedKeysIndex(): dumping used keys files index...");
163

  
164
		for (Map.Entry<String, TreeSet<File>> entry : this.usedKeysFilesIndex.entrySet()) {
165
			System.out.println(entry.getKey());
166
			if(entry.getValue().isEmpty())	{
167
				System.out.println("\t-not used in any file of the workspace-");
168
			}
169
			else	{
170
				for(File file : entry.getValue())	{
171
					System.out.println("\t" + file);
172
				}
173
			}
174
		}
175

  
176
		System.out.println("WorkspacePreferencesManager.dumpUsedKeysFilesIndex(): number of used keys: " + this.usedKeysFilesIndex.size());
177
	}
178

  
179
	/**
180
	 * Save modifications of keys of all known PluginPreferences in all known source files
181
	 * @throws IOException 
182
	 */
183
	public void saveKeyModificationsInSources() throws IOException {
184
//		HashMap<String, String> modifications = new HashMap<String, String>();
185
//
186
//		// stores all modifications
187
//		ArrayList<PluginPreferencesManager> plugins = new ArrayList<PluginPreferencesManager>(pluginsPreferencesPerProject.values());
188
//
189
//		// sort plugins by name length. Needed to not erase a replacement: for messages BPreferences.xx and ABPreferences.xx, ABPreferences.xx should be replaced first
190
//		Collections.sort(plugins, new Comparator<PluginPreferencesManager>() {
191
//			@Override
192
//			public int compare(PluginPreferencesManager arg0, PluginPreferencesManager arg1) {
193
//				return arg1.getPreferenceName().length() - arg0.getPreferenceName().length();
194
//			}
195
//
196
//		});
197
//
198
//		// build the global keys used in sources
199
//		for (PluginPreferencesManager pm : plugins) {
200
//			HashMap<String, String> modifs = pm.getKeyModifications();
201
//			String name = pm.getPreferenceClassName();
202
//
203
//			for (String old : modifs.keySet()) {
204
//				modifications.put(pm.getKeyFullName(old), pm.getKeyFullName(modifs.get(old))); // prefix the key with class name: Key -> XXXPreferences.Key used in sources
205
//			}
206
//		}
207
//
208
//		// update source files
209
//
210
//		// sort keys by name length. Needed to not erase a replacement: for messages BPreferences.xx and ABPreferences.xx, ABPreferences.xx should be replaced first
211
//		ArrayList<String> keys = new ArrayList<String>(modifications.keySet());
212
//		Collections.sort(keys, new Comparator<String>() {
213
//			@Override
214
//			public int compare(String arg0, String arg1) {
215
//				return arg1.length() - arg0.length();
216
//			}
217
//		});
218
//
219
//		System.out.println("Keys to update: "+keys);
220
//		ArrayList<String> updated = new ArrayList<String>();
221
//		//		for (PluginPreferencesManager pm : pluginsPreferencesPerProject.values()) {
222
//		TreeMap<String, TreeSet<File>> index = getUsedKeysFilesIndex();
223
//
224
//		for (String oldKey : keys) {
225
//			if (index.containsKey(oldKey)) {
226
//				TreeSet<File> files = index.get(oldKey);
227
//				if (files.size() > 0) {
228
//					Pattern p = Pattern.compile(oldKey+"([^_0-9a-zA-Z$])");
229
//					System.out.println("Replace KEY="+p+" BY KEY="+modifications.get(oldKey));
230
//					System.out.println("Files: "+files);
231
//					for (File srcFile : files) {
232
//						//FIXME AAAAA remplace "AAAAA" et "AAAAA1"
233
//						IOUtils.replaceAll(srcFile, p, modifications.get(oldKey)+"$1");
234
//					}
235
//					updated.add(oldKey);
236
//				}
237
//			}
238
//		}
239
		//		}
240
	}
241

  
242
	/**
243
	 * @return the Project directory associated with their PluginPreferences
244
	 */
245
	public LinkedHashMap<File, PluginPreferencesManager> getPluginPreferences() {
246
		return pluginsPreferencesPerProject;
247
	}
248

  
249
	public File getWorkspaceLocation() {
250
		return workspaceLocation;
251
	}
252

  
253
	/**
254
	 *  dedicated to get a manager that use the specified key in the project source files for example to move an unused message to another plugin (move dedicated string from core/rcp to dedicated plugin)
255
	 * @param key local key (without the 'XXXPreferences.' part)
256
	 * @return the PluginPreferences that uses the key in source files
257
	 */
258
	public ArrayList<PluginPreferencesManager> getPluginPreferencesManagersUsingKey(String key)	{
259
		ArrayList<PluginPreferencesManager> pms = new ArrayList<>();
260

  
261
		for (PluginPreferencesManager pm : this.getPluginPreferences().values()) {
262
			if (pm.getUsedKeysFilesIndex().containsKey(key)) {
263
				pms.add(pm);
264
			}
265
		}
266

  
267
		return pms;
268
	}
269

  
270

  
271
	/**
272
	 * Creates the index of the keys used and their associated files.
273
	 */
274
	public void createUsedKeysFilesIndex()	{
275
		this.usedKeysFilesIndex = new TreeMap<String, TreeSet<File>>();
276

  
277
		for (File p : this.pluginsPreferencesPerProject.keySet()) {
278
			PluginPreferencesManager pmManager = this.pluginsPreferencesPerProject.get(p);
279

  
280
			TreeMap<String, TreeSet<File>> index = pmManager.getUsedKeysFilesIndex();
281

  
282
			if(index == null) {
283
				System.err.println("WorkspacePreferencesManager.createUsedKeysFilesIndex(): project " + pmManager.getProjectDirectory() + " have no used keys.");
284
				continue;
285
			}
286

  
287
			for (Map.Entry<String, TreeSet<File>> entry :index.entrySet()) {
288

  
289
				if (debug) {
290
					System.out.println("WorkspacePreferencesManager.createUsedKeysFilesIndex(): key added: " + entry.getKey() + ".");
291
				}
292

  
293
				if(this.usedKeysFilesIndex.containsKey(entry.getKey()))	{
294
					this.usedKeysFilesIndex.get(entry.getKey()).addAll(entry.getValue());
295
				}
296
				else	{
297
					this.usedKeysFilesIndex.put(entry.getKey(), entry.getValue());
298
				}
299
			}
300
		}
301
	}
302

  
303

  
304
	/**
305
	 * 
306
	 * @param args
307
	 * @throws UnsupportedEncodingException
308
	 * @throws FileNotFoundException
309
	 * @throws IOException
310
	 */
311
	public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException, IOException {
312
		WorkspacePreferencesManager wmm = new WorkspacePreferencesManager();
313
		for (PluginPreferencesManager preferences : wmm.getPluginPreferences().values()) {
314
			preferences.summary();
315
		}
316
		//wmm.saveKeyModificationsInSources();
317
	}
318
}
0 319

  

Formats disponibles : Unified diff