001: /*
002: * $Id: FlexibleMapAccessor.java,v 1.4 2003/11/25 07:48:13 jonesde Exp $
003: *
004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.base.util;
025:
026: import java.util.HashMap;
027: import java.util.LinkedList;
028: import java.util.List;
029: import java.util.Locale;
030: import java.util.Map;
031:
032: /**
033: * Used to flexibly access Map values, supporting the "." (dot) syntax for
034: * accessing sub-map values and the "[]" (square bracket) syntax for accessing
035: * list elements. See individual Map operations for more information.
036: *
037: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
038: * @version $Revision: 1.4 $
039: * @since 2.1
040: */
041: public class FlexibleMapAccessor {
042:
043: protected String original;
044: protected String extName;
045: protected boolean isListReference = false;
046: protected boolean isAddAtIndex = false;
047: protected boolean isAddAtEnd = false;
048: protected int listIndex = -1;
049: protected SubMapAccessor subMapAccessor = null;
050:
051: public FlexibleMapAccessor(String name) {
052: this .original = name;
053: int dotIndex = name.lastIndexOf('.');
054: if (dotIndex != -1) {
055: this .extName = name.substring(dotIndex + 1);
056: String subName = name.substring(0, dotIndex);
057: this .subMapAccessor = new SubMapAccessor(subName);
058: } else {
059: this .extName = name;
060: }
061: int openBrace = this .extName.indexOf('[');
062: int closeBrace = (openBrace == -1 ? -1 : this .extName.indexOf(
063: ']', openBrace));
064: if (openBrace != -1 && closeBrace != -1) {
065: String liStr = this .extName.substring(openBrace + 1,
066: closeBrace);
067: //if brackets are empty, append to list
068: if (liStr.length() == 0) {
069: this .isAddAtEnd = true;
070: } else {
071: if (liStr.charAt(0) == '+') {
072: liStr = liStr.substring(1);
073: this .listIndex = Integer.parseInt(liStr);
074: this .isAddAtIndex = true;
075: } else {
076: this .listIndex = Integer.parseInt(liStr);
077: }
078: }
079: this .extName = this .extName.substring(0, openBrace);
080: this .isListReference = true;
081: }
082: }
083:
084: public String getOriginalName() {
085: return this .original;
086: }
087:
088: public boolean isEmpty() {
089: if (this .original == null || this .original.length() == 0) {
090: return true;
091: } else {
092: return false;
093: }
094: }
095:
096: /** Given the name based information in this accessor, get the value from the passed in Map.
097: * Supports LocalizedMaps by getting a String or Locale object from the base Map with the key "locale", or by explicit locale parameter.
098: * @param base
099: * @return
100: */
101: public Object get(Map base) {
102: return get(base, null);
103: }
104:
105: /** Given the name based information in this accessor, get the value from the passed in Map.
106: * Supports LocalizedMaps by getting a String or Locale object from the base Map with the key "locale", or by explicit locale parameter.
107: * Note that the localization functionality is only used when the lowest level sub-map implements the LocalizedMap interface
108: * @param base Map to get value from
109: * @param locale Optional locale parameter, if null will see if the base Map contains a "locale" key
110: * @return
111: */
112: public Object get(Map base, Locale locale) {
113: if (base == null) {
114: return null;
115: }
116:
117: // so we can keep the passed context
118: Map newBase = new HashMap(base);
119:
120: if (this .subMapAccessor != null) {
121: newBase = this .subMapAccessor.getSubMap(base);
122: }
123:
124: Object ret = null;
125: if (this .isListReference) {
126: List lst = (List) newBase.get(this .extName);
127: ret = lst.get(this .listIndex);
128: } else {
129: ret = getByLocale(this .extName, base, newBase, locale);
130: }
131:
132: // in case the name has a dot like system env values
133: if (ret == null) {
134: ret = getByLocale(this .original, base, base, locale);
135: }
136:
137: return ret;
138: }
139:
140: protected Object getByLocale(String name, Map base, Map sub,
141: Locale locale) {
142: if (sub instanceof LocalizedMap) {
143: LocalizedMap locMap = (LocalizedMap) sub;
144: if (locale != null) {
145: return locMap.get(name, locale);
146: } else if (base.containsKey("locale")) {
147: return locMap.get(name, UtilMisc.ensureLocale(base
148: .get("locale")));
149: } else {
150: return locMap.get(name, Locale.getDefault());
151: }
152: } else {
153: return sub.get(name);
154: }
155: }
156:
157: /** Given the name based information in this accessor, put the value in the passed in Map.
158: * If the brackets for a list are empty the value will be appended to the list,
159: * otherwise the value will be set in the position of the number in the brackets.
160: * If a "+" (plus sign) is included inside the square brackets before the index
161: * number the value will inserted/added at that point instead of set at the point.
162: * @param base
163: * @param value
164: */
165: public void put(Map base, Object value) {
166: if (base == null) {
167: throw new IllegalArgumentException(
168: "Cannot put a value in a null base Map");
169: }
170: if (this .subMapAccessor != null) {
171: Map subBase = this .subMapAccessor.getSubMap(base);
172: if (subBase == null) {
173: return;
174: }
175: base = subBase;
176: }
177: if (this .isListReference) {
178: List lst = (List) base.get(this .extName);
179: //if brackets are empty, append to list
180: if (this .isAddAtEnd) {
181: lst.add(value);
182: } else {
183: if (this .isAddAtIndex) {
184: lst.add(this .listIndex, value);
185: } else {
186: lst.set(this .listIndex, value);
187: }
188: }
189: } else {
190: base.put(this .extName, value);
191: }
192: }
193:
194: /** Given the name based information in this accessor, remove the value from the passed in Map. * @param base
195: * @param base the Map to remove from
196: * @return the object removed
197: */
198: public Object remove(Map base) {
199: if (this .subMapAccessor != null) {
200: base = this .subMapAccessor.getSubMap(base);
201: }
202: if (this .isListReference) {
203: List lst = (List) base.get(this .extName);
204: return lst.remove(this .listIndex);
205: } else {
206: return base.remove(this .extName);
207: }
208: }
209:
210: public String toString() {
211: return this .original;
212: }
213:
214: public class SubMapAccessor {
215: protected String extName;
216: protected boolean isListReference = false;
217: protected int listIndex = -1;
218: protected SubMapAccessor subMapAccessor = null;
219:
220: public SubMapAccessor(String name) {
221: int dotIndex = name.lastIndexOf('.');
222: if (dotIndex != -1) {
223: this .extName = name.substring(dotIndex + 1);
224: String subName = name.substring(0, dotIndex);
225: this .subMapAccessor = new SubMapAccessor(subName);
226: } else {
227: this .extName = name;
228: }
229: int openBrace = this .extName.indexOf('[');
230: int closeBrace = (openBrace == -1 ? -1 : this .extName
231: .indexOf(']', openBrace));
232: if (openBrace != -1 && closeBrace != -1) {
233: String liStr = this .extName.substring(openBrace + 1,
234: closeBrace);
235: this .listIndex = Integer.parseInt(liStr);
236: this .extName = this .extName.substring(0, openBrace);
237: this .isListReference = true;
238: }
239: }
240:
241: public Map getSubMap(Map base) {
242: if (base == null)
243: return null;
244: if (this .subMapAccessor != null) {
245: base = this .subMapAccessor.getSubMap(base);
246: }
247: if (this .isListReference) {
248: List lst = (List) base.get(this .extName);
249: if (lst == null) {
250: lst = new LinkedList();
251: base.put(this .extName, lst);
252: }
253:
254: Map extMap = null;
255: if (lst.size() > this .listIndex) {
256: extMap = (Map) lst.get(this .listIndex);
257: }
258: if (extMap == null) {
259: extMap = new HashMap();
260: lst.add(this .listIndex, extMap);
261: }
262:
263: return extMap;
264: } else {
265: Map extMap = (Map) base.get(this .extName);
266: if (extMap == null) {
267: extMap = new HashMap();
268: base.put(this .extName, extMap);
269: }
270: return extMap;
271: }
272: }
273: }
274:
275: /*
276: protected Map getNamedMap(String name, Map base) {
277: int dotIndex = name.lastIndexOf('.');
278: if (dotIndex != -1) {
279: String subName = name.substring(0, dotIndex);
280: String extName = name.substring(dotIndex+1);
281: Map subMap = getNamedMap(subName, base);
282: return (Map) this.getMemberCheckList(extName, subMap);
283: } else {
284: return (Map) this.getMemberCheckList(name, base);
285: }
286: }
287:
288: protected Object getMemberCheckList(String name, Map base) {
289: int openBrace = name.indexOf('[');
290: int closeBrace = name.indexOf(']', openBrace);
291: if (openBrace != -1 && closeBrace != -1) {
292: String liStr = name.substring(openBrace+1, closeBrace);
293: int listIndex = Integer.parseInt(liStr);
294: String baseName = name.substring(0, openBrace);
295: List lst = (List) base.get(baseName);
296: return lst.get(listIndex);
297: } else {
298: return base.get(name);
299: }
300: }
301:
302: protected void putMemberCheckList(String name, Map base, Object value) {
303: int openBrace = name.indexOf('[');
304: int closeBrace = name.indexOf(']', openBrace);
305: if (openBrace != -1 && closeBrace != -1) {
306: String baseName = name.substring(0, openBrace);
307: List lst = (List) base.get(baseName);
308:
309: String liStr = name.substring(openBrace+1, closeBrace);
310: //if brackets are empty, append to list
311: if (liStr.length() == 0) {
312: lst.add(value);
313: } else {
314: if (liStr.charAt(0) == '+') {
315: liStr = liStr.substring(1);
316: int listIndex = Integer.parseInt(liStr);
317: lst.add(listIndex, value);
318: } else {
319: int listIndex = Integer.parseInt(liStr);
320: lst.set(listIndex, value);
321: }
322: }
323: } else {
324: base.put(name, value);
325: }
326: }
327:
328: protected Object removeMemberCheckList(String name, Map base) {
329: int openBrace = name.indexOf('[');
330: int closeBrace = name.indexOf(']', openBrace);
331: if (openBrace != -1 && closeBrace != -1) {
332: String liStr = name.substring(openBrace+1, closeBrace);
333: int listIndex = Integer.parseInt(liStr);
334: String baseName = name.substring(0, openBrace);
335: List lst = (List) base.get(baseName);
336: return lst.remove(listIndex);
337: } else {
338: return base.remove(name);
339: }
340: }
341:
342: protected Object getMapMember(String name, Map base) {
343: int dotIndex = name.lastIndexOf('.');
344: if (dotIndex != -1) {
345: String subName = name.substring(0, dotIndex);
346: String extName = name.substring(dotIndex+1);
347: Map subMap = getNamedMap(subName, base);
348: return this.getMemberCheckList(extName, subMap);
349: } else {
350: return this.getMemberCheckList(name, base);
351: }
352: }
353:
354: protected void putMapMember(String name, Map base, Object value) {
355: int dotIndex = name.lastIndexOf('.');
356: if (dotIndex != -1) {
357: String subName = name.substring(0, dotIndex);
358: String extName = name.substring(dotIndex+1);
359: Map subMap = getNamedMap(subName, base);
360: this.putMemberCheckList(extName, subMap, value);
361: } else {
362: this.putMemberCheckList(name, base, value);
363: }
364: }
365:
366: protected Object removeMapMember(String name, Map base) {
367: int dotIndex = name.lastIndexOf('.');
368: if (dotIndex != -1) {
369: String subName = name.substring(0, dotIndex);
370: String extName = name.substring(dotIndex+1);
371: Map subMap = getNamedMap(subName, base);
372: return this.removeMemberCheckList(extName, subMap);
373: } else {
374: return this.removeMemberCheckList(name, base);
375: }
376: }
377: */
378: }
|