001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.base.util.collections;
019:
020: import java.io.Serializable;
021: import java.util.Collection;
022: import java.util.Enumeration;
023: import java.util.HashMap;
024: import java.util.Map;
025: import java.util.MissingResourceException;
026: import java.util.ResourceBundle;
027: import java.util.Set;
028:
029: import org.ofbiz.base.util.UtilProperties;
030:
031: /**
032: * Generic ResourceBundle Map Wrapper, given ResourceBundle allows it to be used as a Map
033: *
034: */
035: public class ResourceBundleMapWrapper implements Map, Serializable {
036:
037: protected MapStack rbmwStack;
038: protected ResourceBundle initialResourceBundle;
039:
040: protected ResourceBundleMapWrapper() {
041: rbmwStack = MapStack.create();
042: }
043:
044: /**
045: * When creating new from a InternalRbmWrapper the one passed to the constructor should be the most specific or local InternalRbmWrapper, with more common ones pushed onto the stack progressively.
046: */
047: public ResourceBundleMapWrapper(
048: InternalRbmWrapper initialInternalRbmWrapper) {
049: this .initialResourceBundle = initialInternalRbmWrapper
050: .getResourceBundle();
051: this .rbmwStack = MapStack.create(initialInternalRbmWrapper);
052: }
053:
054: /**
055: * When creating new from a ResourceBundle the one passed to the constructor should be the most specific or local ResourceBundle, with more common ones pushed onto the stack progressively.
056: */
057: public ResourceBundleMapWrapper(ResourceBundle initialResourceBundle) {
058: if (initialResourceBundle == null) {
059: throw new IllegalArgumentException(
060: "Cannot create ResourceBundleMapWrapper with a null initial ResourceBundle.");
061: }
062: this .initialResourceBundle = initialResourceBundle;
063: this .rbmwStack = MapStack.create(new InternalRbmWrapper(
064: initialResourceBundle));
065: }
066:
067: /** Puts ResourceBundle on the BOTTOM of the stack (bottom meaning will be overriden by higher layers on the stack, ie everything else already there) */
068: public void addBottomResourceBundle(ResourceBundle topResourceBundle) {
069: this .rbmwStack.addToBottom(new InternalRbmWrapper(
070: topResourceBundle));
071: }
072:
073: /** Puts InternalRbmWrapper on the BOTTOM of the stack (bottom meaning will be overriden by higher layers on the stack, ie everything else already there) */
074: public void addBottomResourceBundle(
075: InternalRbmWrapper topInternalRbmWrapper) {
076: this .rbmwStack.addToBottom(topInternalRbmWrapper);
077: }
078:
079: /** Don't pass the locale to make sure it has the same locale as the base */
080: public void addBottomResourceBundle(String resource) {
081: if (this .initialResourceBundle == null) {
082: throw new IllegalArgumentException(
083: "Cannot add bottom resource bundle, this wrapper was not properly initialized (there is no base/initial ResourceBundle).");
084: }
085: this .addBottomResourceBundle(UtilProperties
086: .getInternalRbmWrapper(resource,
087: this .initialResourceBundle.getLocale()));
088: }
089:
090: /** In general we don't want to use this, better to start with the more specific ResourceBundle and add layers of common ones...
091: * Puts ResourceBundle on the top of the stack (top meaning will override lower layers on the stack)
092: */
093: public void pushResourceBundle(ResourceBundle topResourceBundle) {
094: this .rbmwStack.push(new InternalRbmWrapper(topResourceBundle));
095: }
096:
097: public ResourceBundle getInitialResourceBundle() {
098: return this .initialResourceBundle;
099: }
100:
101: public void clear() {
102: this .rbmwStack.clear();
103: }
104:
105: public boolean containsKey(Object arg0) {
106: return this .rbmwStack.containsKey(arg0);
107: }
108:
109: public boolean containsValue(Object arg0) {
110: return this .rbmwStack.containsValue(arg0);
111: }
112:
113: public Set entrySet() {
114: return this .rbmwStack.entrySet();
115: }
116:
117: public Object get(Object arg0) {
118: Object value = this .rbmwStack.get(arg0);
119: if (value == null) {
120: value = arg0;
121: }
122: return value;
123: }
124:
125: public boolean isEmpty() {
126: return this .rbmwStack.isEmpty();
127: }
128:
129: public Set keySet() {
130: return this .keySet();
131: }
132:
133: public Object put(Object key, Object value) {
134: return this .rbmwStack.put(key, value);
135: }
136:
137: public void putAll(Map arg0) {
138: this .rbmwStack.putAll(arg0);
139: }
140:
141: public Object remove(Object arg0) {
142: return this .rbmwStack.remove(arg0);
143: }
144:
145: public int size() {
146: return this .rbmwStack.size();
147: }
148:
149: public Collection values() {
150: return this .rbmwStack.values();
151: }
152:
153: public static class InternalRbmWrapper implements Map, Serializable {
154: protected ResourceBundle resourceBundle;
155: protected Map topLevelMap;
156:
157: public InternalRbmWrapper(ResourceBundle resourceBundle) {
158: if (resourceBundle == null) {
159: throw new IllegalArgumentException(
160: "Cannot create InternalRbmWrapper with a null ResourceBundle.");
161: }
162: this .resourceBundle = resourceBundle;
163: topLevelMap = new HashMap();
164: // NOTE: this does NOT return all keys, ie keys from parent ResourceBundles, so we keep the resourceBundle object to look at when the main Map doesn't have a certain value
165: if (resourceBundle != null) {
166: Enumeration keyNum = resourceBundle.getKeys();
167: while (keyNum.hasMoreElements()) {
168: String key = (String) keyNum.nextElement();
169: //resourceBundleMap.put(key, bundle.getObject(key));
170: Object value = resourceBundle.getObject(key);
171: topLevelMap.put(key, value);
172: }
173: }
174: topLevelMap.put("_RESOURCE_BUNDLE_", resourceBundle);
175: }
176:
177: /* (non-Javadoc)
178: * @see java.util.Map#size()
179: */
180: public int size() {
181: // this is an approximate size, won't include elements from parent bundles
182: return topLevelMap.size() - 1;
183: }
184:
185: /* (non-Javadoc)
186: * @see java.util.Map#isEmpty()
187: */
188: public boolean isEmpty() {
189: return topLevelMap.isEmpty();
190: }
191:
192: /* (non-Javadoc)
193: * @see java.util.Map#containsKey(java.lang.Object)
194: */
195: public boolean containsKey(Object arg0) {
196: if (topLevelMap.containsKey(arg0)) {
197: return true;
198: } else {
199: try {
200: if (this .resourceBundle.getObject((String) arg0) != null) {
201: return true;
202: }
203: } catch (NullPointerException e) {
204: // happens when arg0 is null
205: } catch (MissingResourceException e) {
206: // nope, not found... nothing, will automatically return false below
207: }
208: }
209: return false;
210: }
211:
212: /* (non-Javadoc)
213: * @see java.util.Map#containsValue(java.lang.Object)
214: */
215: public boolean containsValue(Object arg0) {
216: throw new RuntimeException(
217: "Not implemented for ResourceBundleMapWrapper");
218: }
219:
220: /* (non-Javadoc)
221: * @see java.util.Map#get(java.lang.Object)
222: */
223: public Object get(Object arg0) {
224: Object value = this .topLevelMap.get(arg0);
225: if (resourceBundle != null) {
226: if (value == null) {
227: try {
228: value = this .resourceBundle
229: .getObject((String) arg0);
230: } catch (MissingResourceException mre) {
231: // do nothing, this will be handled by recognition that the value is still null
232: }
233: }
234: if (value == null) {
235: try {
236: value = this .resourceBundle
237: .getString((String) arg0);
238: } catch (MissingResourceException mre) {
239: // do nothing, this will be handled by recognition that the value is still null
240: }
241: }
242: }
243: /* we used to do this here, but now we'll do it in the top-level class since doing it here would prevent searching down the stack
244: if (value == null) {
245: value = arg0;
246: }
247: */
248: return value;
249: }
250:
251: /* (non-Javadoc)
252: * @see java.util.Map#put(java.lang.Object, java.lang.Object)
253: */
254: public Object put(Object arg0, Object arg1) {
255: throw new RuntimeException(
256: "Not implemented/allowed for ResourceBundleMapWrapper");
257: }
258:
259: /* (non-Javadoc)
260: * @see java.util.Map#remove(java.lang.Object)
261: */
262: public Object remove(Object arg0) {
263: throw new RuntimeException(
264: "Not implemented for ResourceBundleMapWrapper");
265: }
266:
267: /* (non-Javadoc)
268: * @see java.util.Map#putAll(java.util.Map)
269: */
270: public void putAll(Map arg0) {
271: throw new RuntimeException(
272: "Not implemented for ResourceBundleMapWrapper");
273: }
274:
275: /* (non-Javadoc)
276: * @see java.util.Map#clear()
277: */
278: public void clear() {
279: throw new RuntimeException(
280: "Not implemented for ResourceBundleMapWrapper");
281: }
282:
283: /* (non-Javadoc)
284: * @see java.util.Map#keySet()
285: */
286: public Set keySet() {
287: return this .topLevelMap.keySet();
288: }
289:
290: /* (non-Javadoc)
291: * @see java.util.Map#values()
292: */
293: public Collection values() {
294: return this .topLevelMap.values();
295: }
296:
297: /* (non-Javadoc)
298: * @see java.util.Map#entrySet()
299: */
300: public Set entrySet() {
301: return this .topLevelMap.entrySet();
302: }
303:
304: public ResourceBundle getResourceBundle() {
305: return this .resourceBundle;
306: }
307:
308: /*public String toString() {
309: return this.topLevelMap.toString();
310: }*/
311: }
312: }
|