KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > LocalizedEntryListFactory


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.util;
11
12 import java.util.*;
13 import java.io.*;
14 import org.w3c.dom.*;
15 import org.mmbase.bridge.*;
16 import org.mmbase.bridge.util.Queries;
17 import org.mmbase.bridge.util.xml.query.*;
18 import org.mmbase.util.xml.DocumentSerializable;
19 import org.mmbase.util.xml.DocumentReader;
20 import org.mmbase.util.logging.*;
21
22 /**
23  * These factories can produce Collections based on a Locale (The {@link #get} method is
24  * essential). The other methods besides get are methods to define these lists. There are two ways
25  * to add entries to the produced collections. The first one is to explicitely add them, using the
26  * {@link #add} method. This gives precise control, and the collections can have different orders
27  * for different languages. The size of the collections are always the same, so if for a certain
28  * locale less entries are added, these are completed with the unused keys. If for a certain locale
29  * <em>no</em> entries are added, it will behave itself like as the default locale of {@link
30  * LocalizedString#getDefault}.
31  *
32  * It is also possible to add entire 'bundles'. For this use {@link #addBundle}. When a Collection instance
33  * for a certain Locale is requested these informations are used to call {@link
34  * SortedBundle#getResource}.
35  *
36  * It is possible to mix both methods, so having an enumeration partially defined by a bundle,
37  * partially by explicit values, though this is not recommended.
38  *
39  * @author Michiel Meeuwissen
40  * @version $Id: LocalizedEntryListFactory.java,v 1.39 2006/07/17 07:32:29 pierre Exp $
41  * @since MMBase-1.8
42  */

43 public class LocalizedEntryListFactory implements Serializable, Cloneable JavaDoc {
44
45     private static final Logger log = Logging.getLoggerInstance(LocalizedEntryListFactory.class);
46     private static final long serialVersionUID = 1L; // increase this if object serialization changes (which we shouldn't do!)
47

48     private int size = 0; // number of explicitely added keys
49
private boolean usesCloud = false;
50
51     // we don't use interfaces here, because of Serializability
52
private static class LocalizedEntry implements Serializable, PublicCloneable {
53         private static final long serialVersionUID = 1L;
54         ArrayList entries = new ArrayList(); // List of Map.Entries, Bundles and DocumentSerializable's
55
ArrayList unusedKeys = new ArrayList(); // List of unused keys;
56
public Object JavaDoc clone() {
57             try {
58                 LocalizedEntry clone = (LocalizedEntry) super.clone();
59                 Iterator i = clone.entries.iterator();
60                 clone.entries = new ArrayList();
61                 while(i.hasNext()) {
62                     clone.entries.add(((PublicCloneable)i.next()).clone());
63                 }
64                 clone.unusedKeys = (ArrayList) unusedKeys.clone();
65                 return clone;
66             } catch (CloneNotSupportedException JavaDoc cnse) {
67                 log.error(cnse);
68                 return new LocalizedEntry();
69             }
70         }
71         public String JavaDoc toString() {
72             return "entries:" + entries + "uu:" + unusedKeys;
73         }
74     }
75     private HashMap localized = new HashMap(); // Locale -> LocalizedEntry
76
private ArrayList bundles = new ArrayList(); // contains all Bundles
77
private ArrayList fallBack = new ArrayList(); // List of known keys, used as fallback, if nothing defined for a certain locale
78

79     private DocumentSerializable xml = null;
80
81     public LocalizedEntryListFactory() {
82         localized.put(LocalizedString.getDefault(), new LocalizedEntry());
83     }
84
85
86
87     public boolean isEmpty() {
88         return bundles.size() == 0 && fallBack.size() == 0 && !usesCloud;
89     }
90
91     /**
92      * Adds a value for a certain key and Locale
93      * @return The created Map.Entry.
94      */

95     public Map.Entry add(Locale locale, Serializable key, Serializable value) {
96         if (locale == null) {
97             locale = LocalizedString.getDefault();
98         }
99
100         Entry entry = new Entry(key, value);
101         List unused = add(locale, entry);
102         if (! fallBack.contains(key)) {
103             // this is an as yet unknown key.
104
size++;
105             fallBack.add(key);
106             Iterator i = localized.entrySet().iterator();
107             while (i.hasNext()) {
108                 Map.Entry e = (Map.Entry) i.next();
109                 if (! e.getKey().equals(locale)) {
110                     LocalizedEntry loc = (LocalizedEntry) e.getValue();
111                     loc.unusedKeys.add(key);
112                 }
113             }
114         }
115         unused.remove(key);
116         return entry;
117     }
118
119     /**
120      * Add entry to 'localized'
121      * @param entry the object, which has not Locale support of itself (Entry, DocumentSerializable)
122      * @param locale Can be <code>null</code> too, in which case the default locale is used
123      * @return List of currently unused keys for this locale.
124      */

125
126     protected List add(Locale locale, Object JavaDoc entry) {
127         if (locale == null) {
128             locale = LocalizedString.getDefault();
129         }
130         LocalizedEntry local = (LocalizedEntry) localized.get(locale);
131         if (local == null) {
132             local = new LocalizedEntry();
133             local.entries.addAll(bundles);
134             local.unusedKeys.addAll(fallBack);
135             localized.put(locale, local);
136         }
137
138         // If this locale with variant is added but the parent locale was not yet in the map, then
139
// we first add the parent locale.
140
if (locale.getVariant() != null && !"".equals(locale.getVariant())) {
141             Locale l = new Locale(locale.getLanguage(), locale.getCountry());
142             if (!localized.containsKey(l)) {
143                 add(l, entry);
144             }
145         }
146
147         // If this locale with country is added, but the parent locale (only language) was not yet in
148
// the map, we first add the parent language locale.
149
if (locale.getCountry() != null && !"".equals(locale.getCountry())) {
150             Locale l = new Locale(locale.getLanguage());
151             if (!localized.containsKey(l)) {
152                 add(l, entry);
153             }
154         }
155         local.entries.add(entry);
156         return local.unusedKeys;
157     }
158
159     /**
160      * Adds a bundle, to the (current) end of all maintained collections. Actually, only the
161      * definition of the bundle is added, it is instantiated only later, when requested for a
162      * specific locale.
163      */

164     public void addBundle(String JavaDoc baseName, ClassLoader JavaDoc classLoader, Class JavaDoc constantsProvider, Class JavaDoc wrapper, Comparator comparator) {
165         Bundle b = new Bundle(baseName, classLoader, SortedBundle.getConstantsProvider(constantsProvider), wrapper, comparator);
166         if (bundles.contains(b)) {
167             log.info("Adding bundle " + b + " for second time in " + b + ", because " + Logging.stackTrace());
168         }
169         bundles.add(b);
170         Iterator i = localized.values().iterator();
171         if (!i.hasNext()) {
172             // adding very first localizedlist
173
Locale locale = LocalizedString.getDefault();
174             LocalizedEntry local = new LocalizedEntry();
175             local.entries.add(b);
176             local.unusedKeys.addAll(fallBack);
177         } else while(i.hasNext()) {
178             LocalizedEntry local = (LocalizedEntry) i.next();
179             local.entries.add(b);
180         }
181     }
182
183     /**
184      */

185     public void addQuery(Locale locale, Document queryElement) {
186         DocumentSerializable doc = new DocumentSerializable(queryElement);
187         add(locale, doc);
188         usesCloud = true;
189     }
190
191
192     /**
193      * Defaulting version of {@link #get(Locale, Cloud)}. Using default anonymous cloud.
194      */

195     public List get(final Locale locale) {
196         return get(locale, usesCloud ? getCloud(locale) : null);
197     }
198
199     protected Cloud getCloud(Locale locale) {
200         CloudContext context = ContextProvider.getDefaultCloudContext();
201         if (context.isUp()) {
202             try {
203                 Cloud cloud = context.getCloud("mmbase", "class", null);
204                 if (locale != null) cloud.setLocale(locale);
205                 return cloud;
206             } catch (SecurityException JavaDoc se) {
207                 log.warn("" + se.getMessage());
208                 try {
209                     Cloud cloud = context.getCloud("mmbase");
210                     if (locale != null && cloud != null) cloud.setLocale(locale);
211                     return cloud;
212                 } catch (SecurityException JavaDoc se2) {
213                     return null;
214                 }
215             }
216         } else {
217             return null;
218         }
219     }
220
221     /**
222      * Returns a Collection of Map.Entries for the given Locale. The collection is kind of 'virtual',
223      * it only reflects the underlying memory structures.
224      *
225      * This collection does have a well defined iteration order.
226      *
227      * @param locale The locale of <code>null</code> for the default locale.
228      * @param cloud The cloud to use. Can be <code>null</code> if no queries added (see {@link #addQuery}).
229      * If Locale is <code>null</code>, but cloud isn't, the locale of the cloud is used.
230      */

231     public List /* <Map.Entry> */ get(final Locale locale, final Cloud cloud) {
232         return new AbstractSequentialList () {
233
234             public int size() {
235                 return LocalizedEntryListFactory.this.size(cloud);
236             }
237             public ListIterator listIterator(final int index) {
238                 return new ListIterator() {
239                     int i = -1;
240                     Locale useLocale = locale;
241                     Cloud useCloud = cloud;
242                     {
243                         if (useLocale == null) {
244                             useLocale = useCloud != null ? useCloud.getLocale() : LocalizedString.getDefault();
245                         }
246                         log.debug("using locale " + useLocale);
247                     }
248                     private ChainedIterator iterator = new ChainedIterator();
249                     private Iterator subIterator = null;
250                     private Map.Entry next = null;
251
252                     {
253                         LocalizedEntry loc = (LocalizedEntry) localized.get(useLocale);
254                         if (loc == null) {
255                             loc = (LocalizedEntry) localized.get(LocalizedString.getDefault());
256                         }
257
258                         if (loc == null) {
259                             iterator.addIterator(bundles.iterator());
260                             iterator.addIterator(fallBack.iterator());
261                         } else {
262                             iterator.addIterator(loc.entries.iterator());
263                             iterator.addIterator(loc.unusedKeys.iterator());
264                         }
265
266                         findNext();
267                         while (i < index) next();
268                     }
269                     protected void findNext() {
270                         next = null;
271                         i++;
272                         while(next == null && iterator.hasNext()) {
273                             Object JavaDoc candidate = iterator.next();
274                             if (candidate instanceof Map.Entry) {
275                                 next = (Map.Entry) candidate;
276                             } else if (candidate instanceof Bundle) {
277                                 subIterator = ((Bundle) candidate).get(useLocale).iterator();
278                                 if (subIterator.hasNext()) {
279                                     break;
280                                 } else {
281                                     subIterator = null;
282                                 }
283                             } else if (candidate instanceof DocumentSerializable) {
284                                 Element element = ((DocumentSerializable) candidate).getDocument().getDocumentElement();
285                                 try {
286                                     if (useCloud == null) {
287                                         useCloud = getCloud(useLocale);
288                                         if (useCloud == null) {
289                                             if (log.isDebugEnabled()) {
290                                                 log.debug("Defined query for " + this + " but no cloud provided. Skipping results.");
291                                             }
292                                             continue;
293                                         }
294                                     }
295                                     Query query = QueryReader.parseQuery(element, useCloud, null).query;
296                                     final org.mmbase.bridge.NodeList list = query.getList();
297                                     subIterator = new Iterator() {
298                                             final NodeIterator nodeIterator = list.nodeIterator();
299                                             public boolean hasNext() {
300                                                 return nodeIterator.hasNext();
301                                             }
302                                             public Object JavaDoc next() {
303                                                 org.mmbase.bridge.Node next = nodeIterator.nextNode();
304                                                 return new Entry(next, next.getFunctionValue("gui", null));
305                                             }
306                                             public void remove() {
307                                                 throw new UnsupportedOperationException JavaDoc();
308                                             }
309                                         };
310                                     if (subIterator.hasNext()) {
311                                         break;
312                                     } else {
313                                         subIterator = null;
314                                     }
315                                 } catch (Exception JavaDoc e) {
316                                     log.error(e.getMessage(), e);
317                                 }
318                             } else {
319                                 next = new Entry(candidate, candidate);
320                             }
321                         }
322                     }
323
324                     public boolean hasNext() {
325                         return next != null || subIterator != null;
326                     }
327                     public Object JavaDoc next() {
328                         Map.Entry res;
329                         if (subIterator != null) {
330                             res = (Map.Entry) subIterator.next();
331                             Object JavaDoc key = res.getKey();
332                             if (key != null && key instanceof SortedBundle.ValueWrapper) {
333                                 res = new Entry(((SortedBundle.ValueWrapper) key).getKey(), res.getValue());
334                             }
335                             if (!subIterator.hasNext()) {
336                                 subIterator = null;
337                                 findNext();
338                             }
339                         } else {
340                             res = next;
341                             findNext();
342                         }
343                         return res;
344                     }
345                     public int nextIndex() {
346                         return i;
347                     }
348                     public int previousIndex() {
349                         return i - 1;
350                     }
351                     public boolean hasPrevious() {
352                         // TODO
353
throw new UnsupportedOperationException JavaDoc();
354                     }
355                     public Object JavaDoc previous() {
356                         // TODO
357
throw new UnsupportedOperationException JavaDoc();
358                     }
359                     // this is why we hate java:
360

361
362                     public void remove() {
363                         throw new UnsupportedOperationException JavaDoc();
364                     }
365                     public void remove(int index) {
366                         throw new UnsupportedOperationException JavaDoc();
367                     }
368                     public void add(Object JavaDoc o) {
369                         throw new UnsupportedOperationException JavaDoc();
370                     }
371                     public void set(Object JavaDoc o) {
372                         throw new UnsupportedOperationException JavaDoc();
373                     }
374                 };
375             }
376         };
377     }
378     /**
379      * The size of the collections returned by {@link #get}
380      */

381     public int size(Cloud cloud) {
382         if (cloud == null) cloud = getCloud(LocalizedString.getDefault());
383         int queriesSize = size();
384         Locale locale = cloud == null ? LocalizedString.getDefault() : cloud.getLocale();
385         LocalizedEntry localizedList = (LocalizedEntry) localized.get(locale);
386         if (localizedList == null) {
387             locale = LocalizedString.getDefault();
388             localizedList = (LocalizedEntry) localized.get(locale);
389         }
390         if (localizedList != null) {
391             Iterator i = localizedList.entries.iterator();
392             while (i.hasNext()) {
393                 Object JavaDoc o = i.next();
394                 if (o instanceof Bundle) {
395                     // already in size();
396
} else if (o instanceof DocumentSerializable) {
397                     if (cloud == null) {
398                         cloud = getCloud(null);
399                         if (cloud == null) {
400                             log.debug("Found query but didn't provide cloud, skipping");
401                             continue;
402                         }
403                     }
404                     Element element = ((DocumentSerializable) o).getDocument().getDocumentElement();
405                     try {
406                         queriesSize += Queries.count(QueryReader.parseQuery(element, cloud, null).query);
407                     } catch (Exception JavaDoc e) {
408                         log.warn(e);
409                     }
410                 } else {
411                     queriesSize++;
412                 }
413             }
414             //queriesSize += localizedList.unusedKeys.size();
415
}
416
417         return queriesSize;
418     }
419
420     public int size() {
421         int bundleSize = 0;
422         Iterator i = bundles.iterator();
423         while (i.hasNext()) {
424             Bundle b = (Bundle) i.next();
425             try {
426                 bundleSize += b.get(null).size();
427             } catch (MissingResourceException mre) {
428                 log.error(mre);
429             }
430         }
431         return size + bundleSize;
432     }
433
434     public Object JavaDoc castKey(final Object JavaDoc key) {
435         return castKey(key, null);
436     }
437     /**
438      * Since keys may be somehow wrapped, you can also 'unwrap' by this. If e.g. a constants
439      * provider was used, that values can be indicated by the name of the constants and this method
440      * casts to the value.
441      */

442     public Object JavaDoc castKey(final Object JavaDoc key, final Cloud cloud) {
443         String JavaDoc string = null;
444         Iterator i = bundles.iterator();
445         if (i.hasNext()) {
446             string = Casting.toString(key);
447             while (i.hasNext()) {
448                 Bundle b = (Bundle) i.next();
449                 Class JavaDoc wrapper = b.wrapper;
450                 HashMap constants = b.constantsProvider;
451                 Object JavaDoc nk = SortedBundle.castKey(string, null, constants, wrapper);
452                 if (string != nk) {
453                     if (log.isDebugEnabled()) {
454                         log.debug("Cast " + key + " to " + nk);
455                     }
456                     return nk;
457                 }
458             }
459         }
460         if (usesCloud && cloud != null) {
461             if (string == null) string = Casting.toString(key);
462             if (cloud.hasNode(string)) {
463                 return cloud.getNode(string);
464             }
465         }
466         return key;
467
468     }
469
470     public Object JavaDoc clone() {
471         try {
472             LocalizedEntryListFactory clone = (LocalizedEntryListFactory) super.clone();
473             Iterator j = clone.bundles.iterator();
474             clone.bundles = new ArrayList();
475             while(j.hasNext()) {
476                 clone.bundles.add(((PublicCloneable) j.next()).clone());
477             }
478             Iterator i = clone.localized.entrySet().iterator();
479             clone.localized = new HashMap();
480             while(i.hasNext()) {
481                 Map.Entry entry = (Map.Entry) i.next();
482                 clone.localized.put(entry.getKey(), ((PublicCloneable) entry.getValue()).clone());
483             }
484             clone.fallBack = (ArrayList) fallBack.clone();
485             return clone;
486         } catch (Exception JavaDoc e) {
487             log.error(e.getMessage(), e);
488             return new LocalizedEntryListFactory();
489         }
490     }
491
492     /**
493      * Clears all added keys, bundles and queries.
494      */

495     public void clear() {
496         localized.clear();
497         bundles.clear();
498         fallBack.clear();
499         usesCloud = false;
500         size = 0;
501     }
502
503
504     /**
505      * Given a certain DOM parent element, it configures this LocalizedEntryListFactory with
506      * sub tags of type 'entry' and 'query'
507      */

508
509     public void fillFromXml(final Element enumerationElement, Class JavaDoc wrapperDefault) {
510         xml = new DocumentSerializable(DocumentReader.toDocument(enumerationElement));
511         org.w3c.dom.NodeList JavaDoc childNodes = enumerationElement.getElementsByTagName("query");
512         for (int i = 0; i < childNodes.getLength(); i++) {
513             Element queryElement = (Element) childNodes.item(i);
514             Locale locale = LocalizedString.getLocale(queryElement);
515             addQuery(locale, DocumentReader.toDocument(queryElement));
516         }
517
518
519         childNodes = enumerationElement.getElementsByTagName("entry");
520         for (int i = 0; i < childNodes.getLength(); i++) {
521             Element entryElement = (Element) childNodes.item(i);
522             if (entryElement.hasAttribute("value")) {
523                 String JavaDoc value = entryElement.getAttribute("value");
524                 Locale locale = LocalizedString.getLocale(entryElement);
525                 String JavaDoc display = entryElement.getAttribute("display");
526                 if (display.equals("")) display = value;
527                 Object JavaDoc key = wrapperDefault != null ? Casting.toType(wrapperDefault, null, value) : value;
528                 if (key instanceof java.io.Serializable JavaDoc) {
529                     log.debug("Added " + key + "/" + display + " for " + locale);
530                     add(locale, (java.io.Serializable JavaDoc) key, display);
531                 } else {
532                     log.error("key " + key + " for " + wrapperDefault + " is not serializable, cannot be added to entrylist factory.");
533                 }
534             } else {
535                 String JavaDoc resource = entryElement.getAttribute("basename");
536                 if (! resource.equals("")) {
537                     Comparator comparator = null;
538                     Class JavaDoc wrapper = wrapperDefault;
539                     if (wrapper != null &&
540                         (! Comparable JavaDoc.class.isAssignableFrom(wrapper)) &&
541                         (! Boolean JavaDoc.class.equals(wrapper)) // in java < 1.5 Boolean is not comparable
542
) {
543                         wrapper = null;
544                     }
545
546                     {
547                         String JavaDoc sorterClass = entryElement.getAttribute("sorterclass");
548                         if (!sorterClass.equals("")) {
549                             try {
550                                 Class JavaDoc sorter = Class.forName(sorterClass);
551                                 if (Comparator.class.isAssignableFrom(sorter)) {
552                                     comparator = (Comparator) sorter.newInstance();
553                                 } else {
554                                     wrapper = sorter;
555                                 }
556                             } catch (Exception JavaDoc e) {
557                                 log.error(e);
558                             }
559                         }
560                     }
561                     Class JavaDoc constantsClass = null;
562                     {
563                         String JavaDoc javaConstants = entryElement.getAttribute("javaconstants");
564                         if (!javaConstants.equals("")) {
565                             try {
566                                 constantsClass = Class.forName(javaConstants);
567                             } catch (Exception JavaDoc e) {
568                                 log.error(e);
569                             }
570                         }
571                     }
572                     try {
573                         addBundle(resource, getClass().getClassLoader(), constantsClass,
574                                   wrapper, comparator);
575                     } catch (MissingResourceException mre) {
576                         log.error(mre);
577                     }
578                 } else {
579                     throw new IllegalArgumentException JavaDoc("no 'value' or 'basename' attribute on enumeration entry element");
580                 }
581             }
582             if (log.isDebugEnabled()) {
583                 log.debug("Found enumeration values now " + this);
584             }
585         }
586
587     }
588     public Element toXml() {
589         if (xml == null) {
590             // TODO: generate xml.
591
return null;
592         } else {
593             return xml.getDocument().getDocumentElement();
594         }
595     }
596
597     public String JavaDoc toString() {
598         return "(localized: " + localized + "bundles: " + bundles + "fallBack: " + fallBack + ")";
599     }
600
601     private static class Bundle implements Serializable, PublicCloneable {
602         private static final long serialVersionUID = 1L; // increase this if object serialization changes (which we shouldn't do!)
603

604         private String JavaDoc resource;
605         private ClassLoader JavaDoc classLoader;
606         private HashMap constantsProvider;
607         private Class JavaDoc wrapper;
608         private Comparator comparator;
609
610         // implementation of serializable
611
private void writeObject(ObjectOutputStream out) throws IOException {
612             out.writeUTF(resource);
613             // dont'r write class-loader, it is not serializable
614
out.writeObject(constantsProvider);
615             out.writeObject(wrapper);
616             if (comparator instanceof Serializable) {
617                 out.writeObject(comparator);
618             } else {
619                 out.writeObject((Comparator) null);
620             }
621         }
622         // implementation of serializable
623
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException JavaDoc {
624             resource = in.readUTF();
625             classLoader = getClass().getClassLoader();
626             constantsProvider = (HashMap) in.readObject();
627             wrapper = (Class JavaDoc) in.readObject();
628             comparator = (Comparator) in.readObject();
629         }
630
631
632
633         Bundle(String JavaDoc r, ClassLoader JavaDoc cl, HashMap cp, Class JavaDoc w, Comparator comp) {
634             resource = r; classLoader = cl; constantsProvider = cp ; wrapper = w; comparator = comp;
635         }
636         /**
637          * Collection of Map.Entry's
638          */

639         Collection get(Locale loc) throws MissingResourceException {
640             try {
641                 return SortedBundle.getResource(resource, loc, classLoader, constantsProvider, wrapper, comparator).entrySet();
642             } catch (IllegalArgumentException JavaDoc iae) {
643                 log.error(iae);
644                 return Collections.EMPTY_LIST;
645             }
646         }
647
648
649         public String JavaDoc toString() {
650             return resource + " " + constantsProvider + " " + wrapper + " " + comparator;
651         }
652         public boolean equals(Object JavaDoc o) {
653             if (o instanceof Bundle) {
654                 Bundle b = (Bundle) o;
655                 return
656                     (resource == null ? b.resource == null : resource.equals(b.resource)) &&
657                     (classLoader == null ? b.classLoader == null : classLoader.equals(b.classLoader)) &&
658                     (constantsProvider == null ? b.constantsProvider == null : constantsProvider.equals(b.constantsProvider)) &&
659                     (wrapper == null ? b.wrapper == null : wrapper.equals(b.wrapper)) &&
660                     (comparator == null ? b.comparator == null : comparator.equals(b.comparator));
661
662             } else {
663                 return false;
664             }
665         }
666         public int hashCode() {
667             int result = 0;
668             result = HashCodeUtil.hashCode(result, resource);
669             result = HashCodeUtil.hashCode(result, classLoader);
670             result = HashCodeUtil.hashCode(result, constantsProvider);
671             result = HashCodeUtil.hashCode(result, wrapper);
672             result = HashCodeUtil.hashCode(result, comparator);
673             return result;
674         }
675
676         public Object JavaDoc clone() {
677             log.debug("Cloning bundle " + this);
678             try {
679                 Bundle clone = (Bundle) super.clone();
680                 clone.constantsProvider = constantsProvider != null ? (HashMap) constantsProvider.clone() : null;
681                 return clone;
682             } catch (Exception JavaDoc e) {
683                 log.error(e.getMessage(), e);
684                 return this;
685             }
686         }
687
688     }
689
690     /**
691      * For testing only.
692      */

693     public static void main(String JavaDoc argv[]) {
694         LocalizedEntryListFactory fact = new LocalizedEntryListFactory();
695         String JavaDoc resource1 = "org.mmbase.datatypes.resources.boolean.onoff";
696         String JavaDoc resource2 = "org.mmbase.datatypes.resources.boolean.yesno";
697         Locale nl = new Locale("nl");
698         Locale en = new Locale("en");
699         Locale dk = new Locale("dk");
700         Locale eo = new Locale("eo");
701         fact.add(nl, "a", "hallo");
702         System.out.println("nou " + fact);
703         fact.add(new Locale("nl"), "b", "daag");
704         fact.add(en, "b", "hello");
705         fact.add(en, "a", "good bye");
706         fact.addBundle(resource1, null, null, Boolean JavaDoc.class, SortedBundle.NO_COMPARATOR);
707         fact.add(nl, "c", "doegg");
708         fact.add(dk, new Integer JavaDoc(5), "dk");
709         fact.add(null, "e", "oi");
710         fact.addBundle(resource2, null, null, String JavaDoc.class, SortedBundle.NO_COMPARATOR);
711
712         System.out.println("size: " + fact.size() + " " + fact);
713         System.out.println("en" + fact.get(en));
714         System.out.println("nl" + fact.get(nl));
715         System.out.println("dk" + fact.get(dk));
716         System.out.println("eo" + fact.get(eo));
717
718         LocalizedEntryListFactory fact2 = new LocalizedEntryListFactory();
719         fact2.addBundle("org.mmbase.datatypes.resources.states", null, org.mmbase.module.builders.MMServers.class, SortedBundle.NO_WRAPPER, SortedBundle.NO_COMPARATOR);
720
721         System.out.println("size: " + fact2.size());
722         System.out.println("" + fact2.get(en));
723         System.out.println("" + fact2.get(nl));
724         Object JavaDoc error = fact2.castKey("ERROR", null);
725         System.out.println("ERROR=" + error.getClass().getName() + " " + error);
726
727
728     }
729
730 }
731
Popular Tags