Source Code Cross Referenced for LocalizedString.java in  » Database-ORM » MMBase » org » mmbase » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » MMBase » org.mmbase.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:
003:        This software is OSI Certified Open Source Software.
004:        OSI Certified is a certification mark of the Open Source Initiative.
005:
006:        The license (Mozilla version 1.0) can be read at the MMBase site.
007:        See http://www.MMBase.org/license
008:
009:         */
010:        package org.mmbase.util;
011:
012:        import java.util.*;
013:        import org.mmbase.util.logging.*;
014:        import org.mmbase.util.xml.DocumentReader;
015:        import org.w3c.dom.*;
016:
017:        /**
018:         *<p>
019:         * A String which is localized. There are two mechanisms to find and provide translations: They can
020:         * explicitely be set with {@link #set} (e.g. during parsing an XML), or a resource-bundle can be
021:         * associated with {@link #setBundle}, which will be used to find translations based on the key of
022:         * this object.
023:         *</p>
024:         *<p>
025:         * The 'set' mechanism can also be driven by {@link #fillFromXml}, which provides a sensible way to fill the LocalizedString with
026:         * setting from a sub element of XMLs.
027:         *</p>
028:         *<p>
029:         * The idea is that objects of this type can be used in stead of normal String objects, for error
030:         * messages, descriptions and other texts which need localization (e.g. because they are exposed to
031:         * end-users).
032:         *</p>
033:         *
034:         * @author Michiel Meeuwissen
035:         * @version $Id: LocalizedString.java,v 1.31 2007/05/23 13:19:59 michiel Exp $
036:         * @since MMBase-1.8
037:         */
038:        public class LocalizedString implements  java.io.Serializable, Cloneable {
039:
040:            private static final Logger log = Logging
041:                    .getLoggerInstance(LocalizedString.class);
042:
043:            private static final long serialVersionUID = 1L;
044:
045:            private static Locale defaultLocale = null; // means 'system default' and 'unset'.
046:
047:            /**
048:             * Sets a default locale for this JVM or web-app. When not using it, the locale is the system
049:             * default. Several web-apps do run in one JVM however and it is very imaginable that you want a
050:             * different default for the Locale.
051:             *
052:             * So, this function can be called only once. Calling it the second time will not do
053:             * anything. It returns the already set default locale then, which should probably prompt you to log an error
054:             * or throw an exception or so. Otherwise it returns <code>null</code> indicating that the
055:             * default locale is now what you just set.
056:             */
057:            public static Locale setDefault(Locale locale) {
058:                if (defaultLocale != null)
059:                    return defaultLocale;
060:                defaultLocale = locale;
061:                return null;
062:            }
063:
064:            /**
065:             * Returns the default locale if set, or otherwise the system default ({@link java.util.Locale#getDefault}).
066:             */
067:            public static Locale getDefault() {
068:                return defaultLocale != null ? defaultLocale : Locale
069:                        .getDefault();
070:            }
071:
072:            /**
073:             * Converts a collection of localized strings to a collection of normal strings.
074:             * @param col    Collection of LocalizedString objects
075:             * @param locale Locale to be used for the call to {@link #get(Locale)} which obviously is needed
076:             */
077:            public static Collection<String> toStrings(
078:                    Collection<LocalizedString> col, Locale locale) {
079:                Collection<String> res = new ArrayList<String>();
080:                for (LocalizedString s : col) {
081:                    res.add(s.get(locale));
082:                }
083:                return res;
084:            }
085:
086:            private String key;
087:
088:            private Map<Locale, String> values = null;
089:            private String bundle = null;
090:
091:            // just for the contract of Serializable
092:            protected LocalizedString() {
093:            }
094:
095:            /**
096:             * @param k The key of this String, if k == <code>null</code> then the first set will define it.
097:             */
098:            public LocalizedString(String k) {
099:                key = k;
100:            }
101:
102:            /**
103:             * Gets the key to use as a default and/or for obtaining a value from the bundle
104:             */
105:            public String getKey() {
106:                return key;
107:            }
108:
109:            /**
110:             * Sets the key to use as a default and/or for obtaining a value from the bundle
111:             */
112:            public void setKey(String key) {
113:                this .key = key;
114:            }
115:
116:            /**
117:             * Gets the value for a certain locale. If no match is found, it falls back to the key.
118:             */
119:            public String get(Locale locale) {
120:                if (locale == null) {
121:                    locale = defaultLocale == null ? Locale.getDefault()
122:                            : defaultLocale;
123:                }
124:                if (values != null) {
125:                    String result = values.get(locale);
126:
127:                    if (result != null)
128:                        return result;
129:
130:                    String variant = locale.getVariant();
131:                    String country = locale.getCountry();
132:                    String language = locale.getLanguage();
133:
134:                    if (!"".equals(variant)) {
135:                        result = values.get(new Locale(language, country));
136:                        if (result != null)
137:                            return result;
138:                    }
139:
140:                    if (!"".equals(country)) {
141:                        result = values.get(new Locale(language));
142:                        if (result != null)
143:                            return result;
144:                    }
145:
146:                    // Some LocalizedString instances may have a default value stored with the key 'null'
147:                    // instead of the locale from MMBase. This is the case for values stored while the
148:                    // MMBase module was not yet active.
149:                    // This code 'fixes' that reference.
150:                    // It's not nice, but as a proper fix likely requires a total rewrite of Module.java and
151:                    // MMBase.java, this will have to do for the moment.
152:                    if (locale.equals(defaultLocale)) {
153:                        result = values.get(null);
154:                        if (result != null) {
155:                            values.put(locale, result);
156:                            return result;
157:                        }
158:                    }
159:                }
160:
161:                if (bundle != null) {
162:                    try {
163:                        return ResourceBundle.getBundle(bundle, locale)
164:                                .getString(key);
165:                    } catch (MissingResourceException mre) {
166:                        // fall back to key.
167:                        if (log.isDebugEnabled()) {
168:                            log.debug("Cannot get resource from bundle: "
169:                                    + bundle + ", key: " + key);
170:                        }
171:                    }
172:                }
173:
174:                return key;
175:            }
176:
177:            /**
178:             * Sets the value for a certain locale. If the value for a more general locale is still unset,
179:             * it will also set that (so, it sets also nl when setting nl_BE if nl still is unset).
180:             */
181:            public void set(final String value, Locale locale) {
182:                if (key == null)
183:                    key = value;
184:
185:                if (values == null) {
186:                    values = new HashMap<Locale, String>();
187:                }
188:
189:                if (locale == null) {
190:                    locale = defaultLocale;
191:                }
192:
193:                values.put(locale, value);
194:
195:                if (locale != null) {
196:                    String variant = locale.getVariant();
197:                    String country = locale.getCountry();
198:                    String language = locale.getLanguage();
199:                    if (!"".equals(variant)) {
200:                        Locale loc = new Locale(language, country);
201:                        if (values.get(loc) == null) {
202:                            values.put(loc, value);
203:                        }
204:                    }
205:                    if (!"".equals(country)) {
206:                        Locale loc = new Locale(language);
207:                        if (values.get(loc) == null) {
208:                            values.put(loc, value);
209:                        }
210:                    }
211:                }
212:            }
213:
214:            /**
215:             * Returns a Map representation of the localisation setting represented by this
216:             * LocalizedString. It is an unmodifiable mapping: Locale -> localized value.
217:             */
218:            public Map<Locale, String> asMap() {
219:                if (values == null)
220:                    return Collections.emptyMap();
221:                return Collections.unmodifiableMap(values);
222:            }
223:
224:            /**
225:             * A resource-bundle with given name can be associated to this LocalizedString. If no
226:             * translations were explicitely added, it can be used to look up the translation in the bundle,
227:             * using the key.
228:             */
229:
230:            public void setBundle(String b) {
231:                bundle = b;
232:            }
233:
234:            /**
235:             * {@inheritDoc}
236:             *
237:             * For LocalizedString this returns the String for the default Locale (see {@link #getDefault}).
238:             */
239:            public String toString() {
240:                return get((Locale) null);
241:            }
242:
243:            /**
244:             * This utility takes care of reading the xml:lang attribute from an element
245:             * @param element a DOM element
246:             * @return A {@link java.util.Locale} object, or <code>null</code> if the element did not have,
247:             * or had an empty, xml:lang attribute
248:             */
249:            public static Locale getLocale(Element element) {
250:                return getLocale(element.getAttribute("xml:lang"));
251:            }
252:
253:            /**
254:             * @since MMBase-1.8.1
255:             */
256:            public static Locale getLocale(String xmlLang) {
257:                Locale loc = null;
258:                if (xmlLang != null && (!xmlLang.equals(""))) {
259:
260:                    String[] split = xmlLang.split("[-_]", 3);
261:                    if (split.length == 1) {
262:                        loc = new Locale(split[0]);
263:                    } else if (split.length == 2) {
264:                        loc = new Locale(split[0], split[1]);
265:                    } else {
266:                        loc = new Locale(split[0], split[1], split[2]);
267:                    }
268:                }
269:                return loc;
270:            }
271:
272:            /**
273:             * Degrades a Locale object to a more general Locale. Principally this means that first the
274:             * 'variant' will be dropped and then the country. As an extra the 'variant' is also degraded
275:             * progressively. This is done by taking away parts (from the end) which are separated by
276:             * underscore characters. Also, after degrading the country, also locales are tried with no
277:             * country, but with a variant only.
278:             * So e.g. nl_BE_a_b is degraded to nl_BE_a, then nl_BE, then nl__a_b, then nl__a, then nl.
279:             *
280:             * @param locale The locale to be degraded
281:             * @param originalLocale The original locale (used to find back the original variant after
282:             * dropping the country)
283:             * @return A degraded Locale of <code>null</code> if the locale could not be degraded any further.
284:             *
285:             * @since MMBase-1.8.5
286:             */
287:            public static Locale degrade(Locale locale, Locale originalLocale) {
288:                String language = locale.getLanguage();
289:                String country = locale.getCountry();
290:                String variant = locale.getVariant();
291:                if (variant != null && !"".equals(variant)) {
292:                    String[] var = variant.split("_");
293:                    if (var.length > 1) {
294:                        StringBuilder v = new StringBuilder(var[0]);
295:                        for (int i = 1; i < var.length - 1; i++) {
296:                            v.append('_');
297:                            v.append(var[i]);
298:                        }
299:                        return new Locale(language, country, v.toString());
300:                    } else {
301:                        return new Locale(language, country);
302:                    }
303:                }
304:                if (!"".equals(country)) {
305:                    String originalVariant = originalLocale.getVariant();
306:                    if (originalVariant != null && !"".equals(originalVariant)) {
307:                        return new Locale(language, "", originalVariant);
308:                    } else {
309:                        return new Locale(language);
310:                    }
311:                }
312:                // cannot be degraded any more.
313:                return null;
314:            }
315:
316:            /**
317:             * This utility determines the value of an xml:lang attribute. So, given a {@link java.util.Locale}
318:             * it produces a String.
319:             * @param locale A java locale
320:             * @return A string that can be used as the value for an XML xml:lang attribute.
321:             * @since MMBase-1.8.1
322:             */
323:            public static String getXmlLang(Locale locale) {
324:                if (locale == null)
325:                    return null;
326:                StringBuffer lang = new StringBuffer(locale.getLanguage());
327:                String country = locale.getCountry();
328:                if (country.length() > 0) {
329:                    lang.append("-").append(country);
330:                    String variant = locale.getVariant();
331:                    if (variant != null && variant.length() > 0) {
332:                        lang.append("-").append(variant);
333:                    }
334:                }
335:                return lang.toString();
336:            }
337:
338:            /**
339:             * This utility takes care of setting the xml:lang attribute on an element.
340:             * @param element Element on which the xml:lang attribute is going to be set
341:             * @param locale  Java's Locale object
342:             * @since MMBase-1.8.1
343:             */
344:            public static void setXmlLang(Element element, Locale locale) {
345:                String xmlLang = getXmlLang(locale);
346:                if (xmlLang != null) {
347:                    element.setAttribute("xml:lang", xmlLang);
348:                }
349:            }
350:
351:            /**
352:             * Given a certain tagname, and a DOM parent element, it configures this LocalizedString, using
353:             * subtags with this tagname with 'xml:lang' attributes. This boils down to repeative calls to {@link #set(String, Locale)}.
354:             */
355:
356:            public void fillFromXml(final String tagName, final Element element) {
357:                if (element == null)
358:                    return;
359:                NodeList childNodes = element.getChildNodes();
360:                for (int k = 0; k < childNodes.getLength(); k++) {
361:                    if (childNodes.item(k) instanceof  Element) {
362:                        Element childElement = (Element) childNodes.item(k);
363:                        if (tagName.equals(childElement.getLocalName())) {
364:                            Locale locale = getLocale(childElement);
365:                            String description = DocumentReader
366:                                    .getNodeTextValue(childElement);
367:                            set(description, locale);
368:                        }
369:                    }
370:                }
371:            }
372:
373:            /**
374:             * Writes this LocalizedString object back to an XML, i.e. it searches for and creates
375:             * sub-elements (identified by xml:lang attributes) of a certain given parent element, and sets
376:             * the node-text-value of those elements corresponding to the locale.
377:             * @param tagName Tag-name of the to be used sub-elements
378:             * @param ns      Namespace of the to be created sub-elements, or <code>null</code>
379:             * @param element The parent element which must contain the localized elements.
380:             * @param path    A comma separated list of names of tags which must skipped, before appending
381:             * childs. See {@link org.mmbase.util.xml.DocumentReader#appendChild(Element, Element, String)}.
382:             *
383:             * @since MMBase-1.8.1
384:             */
385:            public void toXml(final String tagName, final String ns,
386:                    final Element element, final String path) {
387:                if (values != null) { // if no explicit values, nothing can be done
388:
389:                    // what if there are corresponding elements already:
390:                    org.w3c.dom.NodeList nl = element
391:                            .getElementsByTagName(tagName);
392:                    for (Map.Entry<Locale, String> entry : values.entrySet()) {
393:                        Locale loc = entry.getKey();
394:                        String value = entry.getValue();
395:                        String xmlLang = getXmlLang(loc);
396:                        // look if such an element is available
397:                        Element child = null;
398:                        for (int j = 0; j < nl.getLength(); j++) {
399:                            Element cand = (Element) nl.item(j);
400:                            if (cand.getAttribute("xml:lang").equals(xmlLang)) {
401:                                child = cand;
402:                                break;
403:                            }
404:                        }
405:                        if (child == null) {
406:                            if (ns != null) {
407:                                child = element.getOwnerDocument()
408:                                        .createElementNS(ns, tagName);
409:                            } else {
410:                                child = element.getOwnerDocument()
411:                                        .createElement(tagName);
412:                            }
413:                            DocumentReader.appendChild(element, child, path);
414:                            setXmlLang(child, loc);
415:                        }
416:                        DocumentReader.setNodeTextValue(child, value);
417:                    }
418:                }
419:            }
420:
421:            public Object clone() {
422:                try {
423:                    LocalizedString clone = (LocalizedString) super .clone();
424:                    if (values != null) {
425:                        clone.values = (Map) ((HashMap) values).clone();
426:                    }
427:                    return clone;
428:                } catch (CloneNotSupportedException cnse) {
429:                    // should not happen
430:                    log.error("Cannot clone this LocalizedString");
431:                    throw new RuntimeException(
432:                            "Cannot clone this LocalizedString", cnse);
433:                }
434:            }
435:
436:            public boolean equals(Object o) {
437:                if (o instanceof  LocalizedString) {
438:                    LocalizedString os = (LocalizedString) o;
439:                    return key.equals(os.key)
440:                            && (values == null ? os.values == null : values
441:                                    .equals(os.values))
442:                            && (bundle == null ? os.bundle == null : bundle
443:                                    .equals(os.bundle));
444:                } else {
445:                    return false;
446:                }
447:            }
448:
449:            public int hashCode() {
450:                int result = 0;
451:                result = HashCodeUtil.hashCode(result, key);
452:                result = HashCodeUtil.hashCode(result, values);
453:                result = HashCodeUtil.hashCode(result, bundle);
454:                return result;
455:            }
456:
457:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.