KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > base > util > collections > FlexibleMapAccessor


1 /*
2  * $Id: FlexibleMapAccessor.java 5720 2005-09-13 03:10:59Z jonesde $
3  *
4  * Copyright (c) 2003-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */

24 package org.ofbiz.base.util.collections;
25
26 import java.io.Serializable JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Locale JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import javolution.util.FastList;
32 import javolution.util.FastMap;
33
34 import org.ofbiz.base.util.Debug;
35 import org.ofbiz.base.util.UtilMisc;
36
37 /**
38  * Used to flexibly access Map values, supporting the "." (dot) syntax for
39  * accessing sub-map values and the "[]" (square bracket) syntax for accessing
40  * list elements. See individual Map operations for more information.
41  *
42  * @author <a HREF="mailto:jonesde@ofbiz.org">David E. Jones</a>
43  * @version $Rev: 5720 $
44  * @since 2.1
45  */

46 public class FlexibleMapAccessor implements Serializable JavaDoc {
47     public static final String JavaDoc module = FlexibleMapAccessor.class.getName();
48
49     protected String JavaDoc original;
50     protected String JavaDoc extName;
51     protected boolean isListReference = false;
52     protected boolean isAddAtIndex = false;
53     protected boolean isAddAtEnd = false;
54     protected boolean isAscending = true;
55     protected int listIndex = -1;
56     protected SubMapAccessor subMapAccessor = null;
57
58     public FlexibleMapAccessor(String JavaDoc name) {
59         this.original = name;
60         
61         // do one quick thing before getting into the Map/List stuff: if it starts with a + or - set the isAscending variable
62
if (name != null && name.length() > 0) {
63             if (name.charAt(0) == '-') {
64                 this.isAscending = false;
65                 name = name.substring(1);
66             } else if (name.charAt(0) == '+') {
67                 this.isAscending = true;
68                 name = name.substring(1);
69             }
70         }
71
72         int dotIndex = name.lastIndexOf('.');
73         if (dotIndex != -1) {
74             this.extName = name.substring(dotIndex+1);
75             String JavaDoc subName = name.substring(0, dotIndex);
76             this.subMapAccessor = new SubMapAccessor(subName);
77         } else {
78             this.extName = name;
79         }
80         int openBrace = this.extName.indexOf('[');
81         int closeBrace = (openBrace == -1 ? -1 : this.extName.indexOf(']', openBrace));
82         if (openBrace != -1 && closeBrace != -1) {
83             String JavaDoc liStr = this.extName.substring(openBrace+1, closeBrace);
84             //if brackets are empty, append to list
85
if (liStr.length() == 0) {
86                 this.isAddAtEnd = true;
87             } else {
88                 if (liStr.charAt(0) == '+') {
89                     liStr = liStr.substring(1);
90                     this.listIndex = Integer.parseInt(liStr);
91                     this.isAddAtIndex = true;
92                 } else {
93                     this.listIndex = Integer.parseInt(liStr);
94                 }
95             }
96             this.extName = this.extName.substring(0, openBrace);
97             this.isListReference = true;
98         }
99     }
100     
101     public String JavaDoc getOriginalName() {
102         return this.original;
103     }
104     
105     public boolean getIsAscending() {
106         return this.isAscending;
107     }
108     
109     public boolean isEmpty() {
110         if (this.original == null || this.original.length() == 0) {
111             return true;
112         } else {
113             return false;
114         }
115     }
116     
117     /** Given the name based information in this accessor, get the value from the passed in Map.
118      * Supports LocalizedMaps by getting a String or Locale object from the base Map with the key "locale", or by explicit locale parameter.
119      * @param base
120      * @return
121      */

122     public Object JavaDoc get(Map JavaDoc base) {
123         return get(base, null);
124     }
125     
126     /** Given the name based information in this accessor, get the value from the passed in Map.
127      * Supports LocalizedMaps by getting a String or Locale object from the base Map with the key "locale", or by explicit locale parameter.
128      * Note that the localization functionality is only used when the lowest level sub-map implements the LocalizedMap interface
129      * @param base Map to get value from
130      * @param locale Optional locale parameter, if null will see if the base Map contains a "locale" key
131      * @return
132      */

133     public Object JavaDoc get(Map JavaDoc base, Locale JavaDoc locale) {
134         if (base == null) {
135             return null;
136         }
137         
138         // so we can keep the passed context
139
Map JavaDoc newBase = null;
140         if (this.subMapAccessor != null) {
141             try {
142                 newBase = this.subMapAccessor.getSubMap(base, false);
143             } catch (Exception JavaDoc e) {
144                 String JavaDoc errMsg = "Error getting map accessor sub-map [" + this.subMapAccessor.extName + "] as part of [" + this.original + "]: " + e.toString();
145                 Debug.logError(e, errMsg, module);
146                 throw new RuntimeException JavaDoc(errMsg);
147             }
148         } else {
149             // DEJ 20041221 was like this, any reason to create a new Map?: newBase = new HashMap(base);
150
newBase = base;
151         }
152         
153         try {
154             Object JavaDoc ret = null;
155             if (this.isListReference) {
156                 List JavaDoc lst = (List JavaDoc) newBase.get(this.extName);
157                 if (lst == null) {
158                     return null;
159                 }
160                 if (lst.size() == 0) {
161                     return null;
162                 }
163                 ret = lst.get(this.isAddAtEnd ? lst.size() -1 : this.listIndex);
164             } else {
165                 ret = getByLocale(this.extName, base, newBase, locale);
166             }
167             
168             // in case the name has a dot like system env values
169
if (ret == null) {
170                 ret = getByLocale(this.original, base, base, locale);
171             }
172             
173             return ret;
174         } catch (Exception JavaDoc e) {
175             String JavaDoc errMsg = "Error getting map accessor entry with name [" + this.extName + "] or [" + this.original + "]: " + e.toString();
176             Debug.logError(e, errMsg, module);
177             throw new RuntimeException JavaDoc(errMsg);
178         }
179     }
180     
181     protected Object JavaDoc getByLocale(String JavaDoc name, Map JavaDoc base, Map JavaDoc sub, Locale JavaDoc locale) {
182         if (sub == null) {
183             return null;
184         }
185         if (sub instanceof LocalizedMap) {
186             LocalizedMap locMap = (LocalizedMap) sub;
187             if (locale != null) {
188                 return locMap.get(name, locale);
189             } else if (base.containsKey("locale")) {
190                 return locMap.get(name, UtilMisc.ensureLocale(base.get("locale")));
191             } else {
192                 return locMap.get(name, Locale.getDefault());
193             }
194         } else {
195             Object JavaDoc getReturn = sub.get(name);
196             return getReturn;
197         }
198     }
199     
200     /** Given the name based information in this accessor, put the value in the passed in Map.
201      * If the brackets for a list are empty the value will be appended to the list,
202      * otherwise the value will be set in the position of the number in the brackets.
203      * If a "+" (plus sign) is included inside the square brackets before the index
204      * number the value will inserted/added at that point instead of set at the point.
205      * @param base
206      * @param value
207      */

208     public void put(Map JavaDoc base, Object JavaDoc value) {
209         if (base == null) {
210             throw new IllegalArgumentException JavaDoc("Cannot put a value in a null base Map");
211         }
212         if (this.subMapAccessor != null) {
213             Map JavaDoc subBase = this.subMapAccessor.getSubMap(base, true);
214             if (subBase == null) {
215                 return;
216             }
217             base = subBase;
218         }
219         if (this.isListReference) {
220             List JavaDoc lst = (List JavaDoc) base.get(this.extName);
221             if (lst == null) {
222                 lst = FastList.newInstance();
223                 base.put(this.extName, lst);
224             }
225             //if brackets are empty, append to list
226
if (this.isAddAtEnd) {
227                 lst.add(value);
228             } else {
229                 if (this.isAddAtIndex) {
230                     lst.add(this.listIndex, value);
231                 } else {
232                     lst.set(this.listIndex, value);
233                 }
234             }
235         } else {
236             base.put(this.extName, value);
237         }
238     }
239     
240     /** Given the name based information in this accessor, remove the value from the passed in Map. * @param base
241      * @param base the Map to remove from
242      * @return the object removed
243      */

244     public Object JavaDoc remove(Map JavaDoc base) {
245         if (this.subMapAccessor != null) {
246             base = this.subMapAccessor.getSubMap(base, false);
247         }
248         if (this.isListReference) {
249             List JavaDoc lst = (List JavaDoc) base.get(this.extName);
250             return lst.remove(this.listIndex);
251         } else {
252             return base.remove(this.extName);
253         }
254     }
255     
256     public String JavaDoc toString() {
257         return this.original;
258     }
259     
260     public boolean equals(Object JavaDoc that) {
261         FlexibleMapAccessor thatAcsr = (FlexibleMapAccessor) that;
262         if (this.original == null) {
263             if (thatAcsr.original == null) {
264                 return true;
265             } else {
266                 return false;
267             }
268         } else {
269             return this.original.equals(thatAcsr.original);
270         }
271     }
272     
273     public int hashCode() {
274         return this.original.hashCode();
275     }
276     
277     public class SubMapAccessor implements Serializable JavaDoc {
278         protected String JavaDoc extName;
279         protected boolean isListReference = false;
280         protected int listIndex = -1;
281         protected SubMapAccessor subMapAccessor = null;
282
283         public SubMapAccessor(String JavaDoc name) {
284             int dotIndex = name.lastIndexOf('.');
285             if (dotIndex != -1) {
286                 this.extName = name.substring(dotIndex+1);
287                 String JavaDoc subName = name.substring(0, dotIndex);
288                 this.subMapAccessor = new SubMapAccessor(subName);
289             } else {
290                 this.extName = name;
291             }
292             int openBrace = this.extName.indexOf('[');
293             int closeBrace = (openBrace == -1 ? -1 : this.extName.indexOf(']', openBrace));
294             if (openBrace != -1 && closeBrace != -1) {
295                 String JavaDoc liStr = this.extName.substring(openBrace+1, closeBrace);
296                 this.listIndex = Integer.parseInt(liStr);
297                 this.extName = this.extName.substring(0, openBrace);
298                 this.isListReference = true;
299             }
300         }
301         
302         public Map JavaDoc getSubMap(Map JavaDoc base, boolean forPut) {
303             if (base == null) return null;
304             if (this.extName == null) return null;
305             if (this.subMapAccessor != null) {
306                 base = this.subMapAccessor.getSubMap(base, forPut);
307             }
308             Object JavaDoc namedObj = base.get(this.extName);
309             if (this.isListReference && (namedObj == null || namedObj instanceof List JavaDoc)) {
310                 List JavaDoc lst = (List JavaDoc) base.get(this.extName);
311                 if (lst == null) {
312                     lst = FastList.newInstance();
313                     base.put(this.extName, lst);
314                 }
315                 
316                 Map JavaDoc extMap = null;
317                 if (lst.size() > this.listIndex) {
318                     extMap = (Map JavaDoc) lst.get(this.listIndex);
319                 }
320                 if (forPut && extMap == null) {
321                     extMap = FastMap.newInstance();
322                     lst.add(this.listIndex, extMap);
323                 }
324                 
325                 return extMap;
326             } else if (namedObj == null || namedObj instanceof Map JavaDoc) {
327                 Map JavaDoc extMap = (Map JavaDoc) namedObj;
328                 
329                 // this code creates a new Map if none is missing, but for a get or remove this is a bad idea...
330
if (forPut && extMap == null) {
331                     extMap = FastMap.newInstance();
332                     base.put(this.extName, extMap);
333                 }
334                 return extMap;
335             } else {
336                 return null;
337             }
338         }
339     }
340 }
341
Popular Tags