Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extI18n / src / org / gvsig / i18n / impl / I18nManagerImpl.java @ 28780

History | View | Annotate | Download (22.9 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 * 
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 * 
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
 * MA  02110-1301, USA.
20
 * 
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {New extension for installation and update of text translations}
26
 */
27
package org.gvsig.i18n.impl;
28

    
29
import java.io.*;
30
import java.security.AccessController;
31
import java.util.*;
32
import java.util.Map.Entry;
33
import java.util.zip.ZipEntry;
34
import java.util.zip.ZipFile;
35
import java.util.zip.ZipOutputStream;
36

    
37
import org.gvsig.i18n.I18nException;
38
import org.gvsig.i18n.I18nManager;
39
import org.gvsig.i18n.Messages;
40

    
41
import sun.security.action.GetPropertyAction;
42

    
43
import com.iver.andami.Launcher;
44
import com.iver.andami.PluginServices;
45
import com.iver.andami.config.generate.AndamiConfig;
46
import com.iver.utiles.StringUtilities;
47
import com.iver.utiles.XMLEntity;
48

    
49
/**
50
 * Implementation of the I18nManager interface.
51
 * 
52
 * @author <a href="mailto:dcervera@disid.com">David Cervera</a>
53
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
54
 */
55
public class I18nManagerImpl implements I18nManager {
56

    
57
    private static final String LOCALES_FILE_NAME = "locales.csv";
58

    
59
    private static final String CSV_SEPARATOR = ",";
60

    
61
    private static final String I18N_EXTENSION = "org.gvsig.i18n";
62

    
63
    private static final String VARIANT = "variant";
64

    
65
    private static final String COUNTRY = "country";
66

    
67
    private static final String LANGUAGE = "language";
68

    
69
    private static final String REGISTERED_LOCALES_PERSISTENCE = "RegisteredLocales";
70

    
71
    private static final I18nManager DEFAULT = new I18nManagerImpl();
72

    
73
    private Set registeredLocales;
74

    
75
    /**
76
     * The list of default reference locales. The last one will be used to get
77
     * all the keys when translating to a new locale.
78
     */
79
    private Locale[] referenceLocales = new Locale[] { ENGLISH, SPANISH };
80

    
81
    private Locale[] defaultLocales = new Locale[] {
82
    // Default supported locales
83
            new Locale("ca"), // Catalan
84
            new Locale("cs"), // Czech
85
            new Locale("de"), // German
86
            ENGLISH, // English
87
            SPANISH, // Spanish
88
            new Locale("eu"), // Basque
89
            new Locale("fr"), // French
90
            new Locale("gl"), // Galician
91
            new Locale("it"), // Italian
92
            new Locale("pl"), // Polish
93
            new Locale("pt"), // Portuguese
94
            new Locale("ro"), // Romanian
95
            new Locale("zh"), // Chinese
96
        new Locale("ru"), // Russian
97
        new Locale("el"), // Greek
98
            new Locale("ro"), // Romanian
99
            new Locale("pl"), // Polish
100
    };
101

    
102
    /**
103
     * Returns the unique instance of the I18nManager.
104
     * 
105
     * @return the unique instance
106
     */
107
    public static I18nManager getInstance() {
108
        return DEFAULT;
109
    }
110

    
111
    public static String capitalize(String text) {
112
        // Convert the first letter to uppercase
113
        String capitalLetter = new String(new char[] { Character
114
                .toUpperCase(text.charAt(0)) });
115
        return capitalLetter.concat(text.substring(1));
116
    }
117

    
118
    /**
119
     * Empty constructor.
120
     */
121
    I18nManagerImpl() {
122
    }
123

    
124
    public Locale[] getInstalledLocales() {
125
        if (registeredLocales == null) {
126

    
127
            XMLEntity child = getRegisteredLocalesPersistence();
128

    
129
            // If the list of registered locales is not already persisted,
130
            // this should be the first time gvSIG is run with the I18nPlugin
131
            // so we will take the list of default locales
132
            if (child == null) {
133
                Locale[] defaultLocales = getDefaultLocales();
134
                registeredLocales = new HashSet(defaultLocales.length);
135
                for (int i = 0; i < defaultLocales.length; i++) {
136
                    registeredLocales.add(defaultLocales[i]);
137
                }
138
                storeInstalledLocales();
139
            } else {
140
                XMLEntity localesEntity = getRegisteredLocalesPersistence();
141
                registeredLocales = new HashSet(localesEntity
142
                        .getChildrenCount());
143
                for (int i = 0; i < localesEntity.getChildrenCount(); i++) {
144
                    XMLEntity localeEntity = localesEntity.getChild(i);
145
                    String language = localeEntity.getStringProperty(LANGUAGE);
146
                    String country = localeEntity.getStringProperty(COUNTRY);
147
                    String variant = localeEntity.getStringProperty(VARIANT);
148
                    Locale locale = new Locale(language, country, variant);
149
                    registeredLocales.add(locale);
150
                }
151
            }
152
        }
153

    
154
        return (Locale[]) registeredLocales
155
                .toArray(new Locale[registeredLocales.size()]);
156
    }
157

    
158
    public void uninstallLocale(Locale locale) throws I18nException {
159
        if (getCurrentLocale().equals(locale) || isReferenceLocale(locale)) {
160
            throw new UninstallLocaleException(locale);
161
        }
162

    
163
        if (registeredLocales.remove(locale)) {
164
            // Remove from the configured locale list
165
            storeInstalledLocales();
166

    
167
            // Remove the resource bundle file
168
            File bundleFile = new File(getResourcesFolder(),
169
                    getResourceFileName(locale));
170

    
171
            if (bundleFile.exists()) {
172
                bundleFile.delete();
173
            }
174
        }
175
    }
176

    
177
    public String getDisplayName(Locale locale) {
178
        return getDisplayName(locale, locale);
179
    }
180

    
181
    public String getDisplayName(Locale locale, Locale displayLocale) {
182
        StringBuffer name = new StringBuffer(getLanguageDisplayName(locale,
183
                displayLocale));
184

    
185
        if (!isEmpty(locale.getCountry())) {
186
            name.append(" - ");
187
            name.append(locale.getDisplayCountry(displayLocale));
188
        }
189

    
190
        if (!isEmpty(locale.getVariant())) {
191
            name.append(" - ");
192
            name.append(locale.getDisplayVariant(displayLocale));
193
        }
194

    
195
        name.append(" (").append(locale.toString()).append(")");
196

    
197
        return name.toString();
198
    }
199

    
200
    private boolean isEmpty(String text) {
201
        return text == null || text.trim().length() == 0;
202
    }
203

    
204
    public String getLanguageDisplayName(Locale locale) {
205
        return getLanguageDisplayName(locale, locale);
206
    }
207

    
208
    public String getLanguageDisplayName(Locale locale, Locale displayLocale) {
209

    
210
        String displayName;
211

    
212
        // Correction for the Basque language display name,
213
        // show it in Basque, not in Spanish
214
        if ("eu".equals(locale.getLanguage())
215
                && "vascuence".equals(locale.getDisplayLanguage())) {
216
            displayName = "Euskera";
217
        }
218
        // Patch for Valencian/Catalan
219
        else if ("ca".equals(locale.getLanguage())) {
220
            // displayName = Messages.getText("__valenciano");
221
            // if ("__valenciano".equals(displayName)) {
222
            // displayName = Messages.getText("__catalan");
223
            // }
224
            displayName = "Valenci?";
225
        } else {
226
            displayName = locale.getDisplayLanguage(displayLocale);
227
        }
228

    
229
        return capitalize(displayName);
230
    }
231

    
232
    public Locale getCurrentLocale() {
233
        return Locale.getDefault();
234
    }
235

    
236
    public Locale getDefaultSystemLocale() {
237
        String language, region, country, variant;
238
        language = (String) AccessController
239
                .doPrivileged(new GetPropertyAction("user.language", "en"));
240
        // for compatibility, check for old user.region property
241
        region = (String) AccessController.doPrivileged(new GetPropertyAction(
242
                "user.region"));
243
        if (region != null) {
244
            // region can be of form country, country_variant, or _variant
245
            int i = region.indexOf('_');
246
            if (i >= 0) {
247
                country = region.substring(0, i);
248
                variant = region.substring(i + 1);
249
            } else {
250
                country = region;
251
                variant = "";
252
            }
253
        } else {
254
            country = (String) AccessController
255
                    .doPrivileged(new GetPropertyAction("user.country", ""));
256
            variant = (String) AccessController
257
                    .doPrivileged(new GetPropertyAction("user.variant", ""));
258
        }
259
        return new Locale(language, country, variant);
260
    }
261

    
262
    public void setCurrentLocale(Locale locale) {
263
        AndamiConfig config = Launcher.getAndamiConfig();
264
        config.setLocaleLanguage(locale.getLanguage());
265
        config.setLocaleCountry(locale.getCountry());
266
        config.setLocaleVariant(locale.getVariant());
267
    }
268

    
269
    public Locale[] installLocales(File importFile) throws I18nException {
270
        List importLocales = new ArrayList();
271

    
272
        try {
273
            ZipFile zipFile = new ZipFile(importFile);
274

    
275
            Map locales = getZipFileNonReferenceLocales(zipFile);
276

    
277
            if (locales == null || locales.size() == 0) {
278
                return null;
279
            }
280

    
281
            for (Iterator iterator = locales.entrySet().iterator(); iterator
282
                    .hasNext();) {
283
                Entry entry = (Entry) iterator.next();
284

    
285
                String fileName = (String) entry.getKey();
286
                Locale locale = (Locale) entry.getValue();
287
                importLocales.add(locale);
288

    
289
                // Add the locale to the list of installed ones, if it
290
                // is new, otherwise, update the texts.
291
                if (!registeredLocales.contains(locale)) {
292
                    registeredLocales.add(locale);
293
                    storeInstalledLocales();
294
                }
295

    
296
                // Replace the old bundle with the new one
297
                ZipEntry zipEntry = zipFile.getEntry(fileName);
298
                InputStream is = zipFile.getInputStream(zipEntry);
299
                BufferedReader reader = new BufferedReader(
300
                        new InputStreamReader(is));
301

    
302
                File bundleFile = getResourceFile(locale);
303
                FileWriter fileWriter = new FileWriter(bundleFile);
304
                BufferedWriter writer = new BufferedWriter(fileWriter);
305

    
306
                String line;
307
                while ((line = reader.readLine()) != null) {
308
                    writer.write(line);
309
                    writer.write('\n');
310
                }
311
                writer.flush();
312
                writer.close();
313
                fileWriter.close();
314
                reader.close();
315
                is.close();
316
            }
317

    
318
        } catch (Exception ex) {
319
            throw new InstallLocalesException(importFile, ex);
320
        }
321

    
322
        return (Locale[]) importLocales
323
                .toArray(new Locale[importLocales.size()]);
324
    }
325

    
326
    public void exportLocaleForUpdate(Locale locale, Locale referenceLocale,
327
            File exportFile) throws I18nException {
328

    
329
        exportLocalesForUpdate(new Locale[] { locale }, referenceLocale,
330
                exportFile);
331
    }
332

    
333
    public void exportLocalesForUpdate(Locale[] locales,
334
            Locale referenceLocale, File exportFile) throws I18nException {
335

    
336
        exportLocale(locales, new Locale[] { referenceLocale }, exportFile,
337
                true);
338
    }
339
    
340
    public void exportLocaleForTranslation(Locale locale,
341
            Locale referenceLocale, File exportFile) throws I18nException {
342
        
343
        exportLocaleForTranslation(locale, new Locale[] { referenceLocale },
344
                exportFile);
345
    }
346

    
347
    public void exportLocaleForTranslation(Locale locale,
348
            Locale[] referenceLocales, File exportFile) throws I18nException {
349

    
350
        exportLocale(new Locale[] { locale }, referenceLocales, exportFile,
351
                false);
352
    }
353

    
354
    public Locale[] getReferenceLocales() {
355
        return referenceLocales;
356
    }
357

    
358
    public void setReferenceLocales(Locale[] referenceLocales) {
359
        this.referenceLocales = referenceLocales;
360
    }
361

    
362
    public void setDefaultLocales(Locale[] defaultLocales) {
363
        this.defaultLocales = defaultLocales;
364
    }
365

    
366
    private void exportLocale(Locale[] locales, Locale[] referenceLocales,
367
            File exportFile, boolean update) throws I18nException {
368

    
369
        Locale[] refArray = getReferenceLocalesToExport(locales,
370
                referenceLocales);
371

    
372
        try {
373
            FileOutputStream fos = new FileOutputStream(exportFile);
374
            ZipOutputStream zipos = new ZipOutputStream(fos);
375

    
376
            // Create the index file
377
            writeZipFileLocales(zipos, locales, refArray);
378

    
379
            PrintStream ps = new PrintStream(zipos);
380
            Map texts = null;
381

    
382
            if (update) {
383
                // First, export the locales to update
384
                if (locales != null) {
385
                    for (int i = 0; i < locales.length; i++) {
386
                        texts = getAllTexts(locales[i]);
387
                        putResourceInZip(zipos, ps, texts,
388
                                getResourceFileName(locales[i]));
389
                    }
390
                }
391
            } else { // translate
392
                // First, export the locales to translate, taking the keys from
393
                // the reference locales, but without values
394
                // We will use the keys of the reference locales
395
                texts = getAllTexts(referenceLocales[0]);
396
                if (locales != null) {
397
                    for (int i = 0; i < locales.length; i++) {
398
                        putResourceInZip(zipos, ps, texts,
399
                                getResourceFileName(locales[i]), false);
400
                    }
401
                }
402
            }
403

    
404
            // Next, export the reference locales
405
            if (refArray != null) {
406
                for (int i = 0; i < refArray.length; i++) {
407
                    texts = getAllTexts(refArray[i]);
408
                    putResourceInZip(zipos, ps, texts,
409
                            getResourceFileName(refArray[i]));
410
                }
411
            }
412

    
413
            ps.flush();
414
            ps.close();
415
            zipos.close();
416
            fos.close();
417
        } catch (IOException ex) {
418
            throw new ExportLocaleException(locales, ex);
419
        }
420
    }
421

    
422
    /**
423
     * Returns the list of reference locales to export, as the union of the
424
     * default reference locales list and the one selected as reference. The
425
     * locales to translate or update are extracted from the list.
426
     */
427
    private Locale[] getReferenceLocalesToExport(Locale[] locales,
428
            Locale[] referenceLocalesSelected) {
429
        // The reference locales to export are the default ones plus the
430
        // selected by the user.
431
        Set exportRefLocales = new HashSet(referenceLocales.length);
432
        for (int i = 0; i < referenceLocales.length; i++) {
433
            exportRefLocales.add(referenceLocales[i]);
434
        }
435
        if (referenceLocalesSelected != null) {
436
            for (int i = 0; i < referenceLocalesSelected.length; i++) {
437
                exportRefLocales.add(referenceLocalesSelected[i]);
438
            }
439
        }
440
        if (locales != null) {
441
            for (int i = 0; i < locales.length; i++) {
442
                exportRefLocales.remove(locales[i]);
443
            }
444
        }
445
        Locale[] refArray = (Locale[]) exportRefLocales
446
                .toArray(new Locale[exportRefLocales.size()]);
447
        return refArray;
448
    }
449

    
450
    /**
451
     * Returns all the localized texts and its keys for a locale.
452
     */
453
    private Map getAllTexts(Locale locale) {
454
        return Messages.getAllTexts(locale);
455
    }
456

    
457
    private Map getZipFileNonReferenceLocales(ZipFile zipFile)
458
            throws I18nException {
459
        ZipEntry zipEntry = zipFile.getEntry(LOCALES_FILE_NAME);
460

    
461
        if (zipEntry == null) {
462
            return null;
463
        }
464

    
465
        Map locales;
466
        try {
467
            InputStream is = zipFile.getInputStream(zipEntry);
468
            BufferedReader reader = new BufferedReader(
469
                    new InputStreamReader(is));
470

    
471
            locales = new HashMap(2);
472
            String line;
473
            while ((line = reader.readLine()) != null) {
474
                // The excepted format is:
475
                // FILENAME,LANGUAGE,COUNTRY,VARIANT,IS_REFERENCE
476
                StringTokenizer st = new StringTokenizer(line, CSV_SEPARATOR,
477
                        true);
478
                // First: locale file name (required)
479
                String fileName = st.nextToken();
480
                if (CSV_SEPARATOR.equals(fileName)) {
481
                    throw new LocaleFileNameRequiredException(line);
482
                } else {
483
                    // Read the next separator
484
                    st.nextToken();
485
                }
486
                // Second: the locale language (required)
487
                String language = st.nextToken();
488
                if (CSV_SEPARATOR.equals(language)) {
489
                    throw new LocaleLanguageRequiredException(line);
490
                } else {
491
                    // Read the next separator
492
                    st.nextToken();
493
                }
494
                // Third: the country
495
                String country = st.nextToken();
496
                if (CSV_SEPARATOR.equals(country)) {
497
                    country = null;
498
                } else {
499
                    // Read the next separator
500
                    st.nextToken();
501
                }
502
                // Fourth: the variant
503
                String variant = st.nextToken();
504
                if (CSV_SEPARATOR.equals(variant)) {
505
                    variant = null;
506
                } else {
507
                    // Read the next separator
508
                    st.nextToken();
509
                }
510
                // Fifth: is a reference locale?
511
                String refStr = st.nextToken();
512
                if (CSV_SEPARATOR.equals(refStr)) {
513
                    refStr = null;
514
                }
515

    
516
                // Only add non reference locales
517
                if (refStr != null && !"true".equals(refStr.toLowerCase())) {
518
                    // Variant only accepted if country defined
519
                    if (country == null) {
520
                        variant = null;
521
                    }
522
                    country = country == null ? "" : country;
523
                    variant = variant == null ? "" : variant;
524
                    Locale locale = new Locale(language, country, variant);
525

    
526
                    locales.put(fileName, locale);
527
                }
528
            }
529

    
530
            reader.close();
531
            is.close();
532
        } catch (IOException ex) {
533
            throw new ReadCSVLocalesFileException(ex);
534
        }
535

    
536
        return locales;
537
    }
538

    
539
    private void writeZipFileLocales(ZipOutputStream zos, Locale[] locales,
540
            Locale[] referenceLocales) throws IOException {
541
        ZipEntry zipEntry = new ZipEntry(LOCALES_FILE_NAME);
542

    
543
        zos.putNextEntry(zipEntry);
544
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(zos));
545

    
546
        if (locales != null) {
547
            for (int i = 0; i < locales.length; i++) {
548
                writeLocaleEntry(locales[i], writer, false);
549
            }
550
        }
551
        if (referenceLocales != null) {
552
            for (int i = 0; i < referenceLocales.length; i++) {
553
                writeLocaleEntry(referenceLocales[i], writer, true);
554
            }
555
        }
556

    
557
        writer.flush();
558
        zos.closeEntry();
559
    }
560

    
561
    /**
562
     * Writes the locale entry into a writer.
563
     * 
564
     * @param locale
565
     *            the locale to create the entry for
566
     * @param writer
567
     *            to write to
568
     * @param reference
569
     *            is it is a reference locale or not
570
     * @throws IOException
571
     *             if there is an error creating the locale entry
572
     */
573
    private void writeLocaleEntry(Locale locale, BufferedWriter writer,
574
            boolean reference) throws IOException {
575
        String language = locale.getLanguage();
576
        String country = locale.getCountry();
577
        country = country == null ? "" : country;
578
        String variant = locale.getVariant();
579
        variant = variant == null ? "" : variant;
580

    
581
        writer.write(getResourceFileName(locale));
582
        writer.write(',');
583
        writer.write(language);
584
        writer.write(',');
585
        writer.write(country);
586
        writer.write(',');
587
        writer.write(variant);
588
        writer.write(',');
589
        writer.write(Boolean.toString(reference));
590
        writer.write('\n');
591
    }
592

    
593
    /**
594
     * Returns if a locale is one of the default reference ones.
595
     */
596
    private boolean isReferenceLocale(Locale locale) {
597
        for (int i = 0; i < referenceLocales.length; i++) {
598
            if (referenceLocales[i].equals(locale)) {
599
                return true;
600
            }
601
        }
602
        return false;
603
    }
604

    
605
    /**
606
     * Puts a new resource file into a Jar file.
607
     */
608
    private void putResourceInZip(ZipOutputStream zipos, PrintStream ps,
609
            Map texts, String resourceFileName) throws IOException {
610

    
611
        putResourceInZip(zipos, ps, texts, resourceFileName, true);
612
    }
613

    
614
    /**
615
     * Puts a new resource file into a Jar file.
616
     */
617
    private void putResourceInZip(ZipOutputStream zipos, PrintStream ps,
618
            Map texts, String resourceFileName, boolean withValue)
619
            throws IOException {
620
        // Add ZIP entry for the resource bundle file
621
        zipos.putNextEntry(new ZipEntry(resourceFileName));
622

    
623
        for (Iterator iterator = texts.entrySet().iterator(); iterator
624
                .hasNext();) {
625
            Entry entry = (Entry) iterator.next();
626
            String keyEncoded = escape((String) entry.getKey(), true);
627
            ps.print(keyEncoded);
628
            ps.print("=");
629
            if (withValue) {
630
                String valueEncoded = escape((String) entry.getValue(), false);
631
                ps.println(valueEncoded);
632
            } else {
633
                ps.println();
634
            }
635
        }
636

    
637
        ps.flush();
638

    
639
        // Close the ZIP entry, the file is complete
640
        zipos.closeEntry();
641
    }
642

    
643
    /**
644
     * Returns the file which contains the translations for a locale.
645
     */
646
    private File getResourceFile(Locale locale) {
647
        return new File(getResourcesFolder(), getResourceFileName(locale));
648
    }
649

    
650
    /**
651
     * Returns the name of the file which contains the translations for a
652
     * locale.
653
     */
654
    private String getResourceFileName(Locale locale) {
655
        StringBuffer fileName = new StringBuffer("text");
656

    
657
        // Spanish without country is the default locale
658
        if (!(isEmpty(locale.getCountry()) && "es".equals(locale.getLanguage()))) {
659
            fileName.append('_').append(locale.getLanguage());
660
        }
661

    
662
        // Add the locale country
663
        if (!isEmpty(locale.getCountry())) {
664
            fileName.append('_').append(locale.getCountry());
665
        }
666

    
667
        // Add the locale variant
668
        if (!isEmpty(locale.getVariant())) {
669
            fileName.append('_').append(locale.getVariant());
670
        }
671

    
672
        fileName.append(".properties");
673
        return fileName.toString();
674
    }
675

    
676
    /**
677
     * Returns the folder where to store the resource bundle files.
678
     */
679
    private File getResourcesFolder() {
680
        return PluginServices.getPluginServices("com.iver.cit.gvsig")
681
                .getPluginDirectory();
682
    }
683

    
684
    /**
685
     * Returns the child XMLEntity with the RegisteredLocales.
686
     */
687
    private XMLEntity getRegisteredLocalesPersistence() {
688
        XMLEntity entity = getI18nPersistence();
689
        XMLEntity child = null;
690
        for (int i = entity.getChildrenCount() - 1; i >= 0; i--) {
691
            XMLEntity tmpchild = entity.getChild(i);
692
            if (tmpchild.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
693
                child = tmpchild;
694
                break;
695
            }
696
        }
697
        return child;
698
    }
699

    
700
    /**
701
     * Returns the I18n Plugin persistence.
702
     */
703
    private XMLEntity getI18nPersistence() {
704
        XMLEntity entity = PluginServices.getPluginServices(I18N_EXTENSION)
705
                .getPersistentXML();
706
        return entity;
707
    }
708

    
709
    /**
710
     * Returns the list of default locales bundled with gvSIG.
711
     */
712
    private Locale[] getDefaultLocales() {
713
        return defaultLocales;
714
    }
715

    
716
    /**
717
     * Stores the list of installed locales into the plugin persistence.
718
     */
719
    private void storeInstalledLocales() {
720
        XMLEntity localesEntity = getRegisteredLocalesPersistence();
721

    
722
        // Remove the previous list of registered languages
723
        if (localesEntity != null) {
724
            XMLEntity i18nPersistence = getI18nPersistence();
725
            for (int i = i18nPersistence.getChildrenCount() - 1; i >= 0; i--) {
726
                XMLEntity child = i18nPersistence.getChild(i);
727
                if (child.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
728
                    i18nPersistence.removeChild(i);
729
                    break;
730
                }
731
            }
732
        }
733

    
734
        // Create the new persistence for the registered languages
735
        localesEntity = new XMLEntity();
736

    
737
        localesEntity.setName(REGISTERED_LOCALES_PERSISTENCE);
738

    
739
        for (Iterator iterator = registeredLocales.iterator(); iterator
740
                .hasNext();) {
741
            Locale locale = (Locale) iterator.next();
742
            XMLEntity localeEntity = new XMLEntity();
743
            localeEntity.setName(locale.getDisplayName());
744
            localeEntity.putProperty(LANGUAGE, locale.getLanguage());
745
            localeEntity.putProperty(COUNTRY, locale.getCountry());
746
            localeEntity.putProperty(VARIANT, locale.getVariant());
747

    
748
            localesEntity.addChild(localeEntity);
749
        }
750

    
751
        getI18nPersistence().addChild(localesEntity);
752
    }
753

    
754
    private String escape(String value, boolean replaceBlanks) {
755
        // First replace non printable characters
756
        if (replaceBlanks) {
757
            value = StringUtilities.replace(value, " ", "\\ ");
758
        }
759
        value = StringUtilities.replace(value, ":", "\\:");
760
        value = StringUtilities.replace(value, "\n", "\\n");
761
        value = StringUtilities.replace(value, "\t", "\\t");
762
        value = StringUtilities.replace(value, "\b", "\\b");
763
        value = StringUtilities.replace(value, "\f", "\\f");
764
        value = StringUtilities.replace(value, "\r", "\\r");
765
        // value = StringUtilities.replace(value, "\\", "\\\\");
766
        // value = StringUtilities.replace(value, "\'", "\\\'");
767
        // value = StringUtilities.replace(value, "\"", "\\\"");
768

    
769
        // Next, encode in raw-unicode-escape
770
        return toRawUnicodeEncoded(value);
771
    }
772

    
773
    private String toRawUnicodeEncoded(String value) {
774
        StringBuffer sb = new StringBuffer();
775
        for (int i = 0; i < value.length(); i++) {
776
            char c = value.charAt(i);
777
            if (c <= 0x80) {
778
                sb.append(c);
779
            } else {
780
                sb.append("\\u");
781
                String hexValue = Integer.toHexString((int) c);
782
                // Append 0 if the hex value has less than 4 digits
783
                for (int j = hexValue.length(); j < 4; j++) {
784
                    sb.append('0');
785
                }
786
                sb.append(hexValue);
787
            }
788
        }
789
        return sb.toString();
790
    }
791
}