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;
019:
020: import java.math.BigDecimal;
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.Collections;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026: import java.util.List;
027: import java.util.Locale;
028: import java.util.Map;
029: import java.util.TreeMap;
030: import org.ofbiz.base.util.UtilProperties;
031:
032: import javolution.util.FastList;
033: import javolution.util.FastMap;
034:
035: import org.ofbiz.base.util.collections.MapComparator;
036:
037: /**
038: * UtilMisc - Misc Utility Functions
039: */
040: public class UtilMisc {
041:
042: public static final String module = UtilMisc.class.getName();
043:
044: public static final BigDecimal ZERO_BD = new BigDecimal(0.0);
045:
046: /**
047: * Get an iterator from a collection, returning null if collection is null
048: * @param col The collection to be turned in to an iterator
049: * @return The resulting Iterator
050: */
051: public static Iterator toIterator(Collection col) {
052: if (col == null)
053: return null;
054: else
055: return col.iterator();
056: }
057:
058: /**
059: * Create a map from passed nameX, valueX parameters
060: * @return The resulting Map
061: */
062: public static Map toMap(String name1, Object value1) {
063: return new UtilMisc.SimpleMap(name1, value1);
064:
065: /* Map fields = FastMap.newInstance();
066: fields.put(name1, value1);
067: return fields;*/
068: }
069:
070: /**
071: * Create a map from passed nameX, valueX parameters
072: * @return The resulting Map
073: */
074: public static Map toMap(String name1, Object value1, String name2,
075: Object value2) {
076: return new UtilMisc.SimpleMap(name1, value1, name2, value2);
077:
078: /* Map fields = FastMap.newInstance();
079: fields.put(name1, value1);
080: fields.put(name2, value2);
081: return fields;*/
082: }
083:
084: /**
085: * Create a map from passed nameX, valueX parameters
086: * @return The resulting Map
087: */
088: public static Map toMap(String name1, Object value1, String name2,
089: Object value2, String name3, Object value3) {
090: return new UtilMisc.SimpleMap(name1, value1, name2, value2,
091: name3, value3);
092:
093: /* Map fields = FastMap.newInstance();
094: fields.put(name1, value1);
095: fields.put(name2, value2);
096: fields.put(name3, value3);
097: return fields;*/
098: }
099:
100: /**
101: * Create a map from passed nameX, valueX parameters
102: * @return The resulting Map
103: */
104: public static Map toMap(String name1, Object value1, String name2,
105: Object value2, String name3, Object value3, String name4,
106: Object value4) {
107: return new UtilMisc.SimpleMap(name1, value1, name2, value2,
108: name3, value3, name4, value4);
109:
110: /* Map fields = FastMap.newInstance();
111: fields.put(name1, value1);
112: fields.put(name2, value2);
113: fields.put(name3, value3);
114: fields.put(name4, value4);
115: return fields;*/
116: }
117:
118: /**
119: * Create a map from passed nameX, valueX parameters
120: * @return The resulting Map
121: */
122: public static Map toMap(String name1, Object value1, String name2,
123: Object value2, String name3, Object value3, String name4,
124: Object value4, String name5, Object value5) {
125: Map fields = FastMap.newInstance();
126:
127: fields.put(name1, value1);
128: fields.put(name2, value2);
129: fields.put(name3, value3);
130: fields.put(name4, value4);
131: fields.put(name5, value5);
132: return fields;
133: }
134:
135: /**
136: * Create a map from passed nameX, valueX parameters
137: * @return The resulting Map
138: */
139: public static Map toMap(String name1, Object value1, String name2,
140: Object value2, String name3, Object value3, String name4,
141: Object value4, String name5, Object value5, String name6,
142: Object value6) {
143: Map fields = FastMap.newInstance();
144:
145: fields.put(name1, value1);
146: fields.put(name2, value2);
147: fields.put(name3, value3);
148: fields.put(name4, value4);
149: fields.put(name5, value5);
150: fields.put(name6, value6);
151: return fields;
152: }
153:
154: /**
155: * Create a map from passed nameX, valueX parameters
156: * @return The resulting Map
157: */
158: public static Map toMap(Object[] data) {
159: if (data == null) {
160: return null;
161: }
162: if (data.length % 2 == 1) {
163: throw new IllegalArgumentException(
164: "You must pass an even sized array to the toMap method");
165: }
166: Map map = FastMap.newInstance();
167: for (int i = 0; i < data.length;) {
168: map.put(data[i++], data[i++]);
169: }
170: return map;
171: }
172:
173: public static String printMap(Map theMap) {
174: StringBuffer theBuf = new StringBuffer();
175: Iterator entryIter = theMap.entrySet().iterator();
176: while (entryIter.hasNext()) {
177: Map.Entry entry = (Map.Entry) entryIter.next();
178: theBuf.append(entry.getKey());
179: theBuf.append(" --> ");
180: theBuf.append(entry.getValue());
181: theBuf.append(System.getProperty("line.separator"));
182: }
183: return theBuf.toString();
184: }
185:
186: /**
187: * Sort a List of Maps by specified consistent keys.
188: * @param listOfMaps List of Map objects to sort.
189: * @param sortKeys List of Map keys to sort by.
190: * @return a new List of sorted Maps.
191: */
192: public static List sortMaps(List listOfMaps, List sortKeys) {
193: if (listOfMaps == null || sortKeys == null)
194: return null;
195: List toSort = FastList.newInstance();
196: toSort.addAll(listOfMaps);
197: try {
198: MapComparator mc = new MapComparator(sortKeys);
199: Collections.sort(toSort, mc);
200: } catch (Exception e) {
201: Debug.logError(e,
202: "Problems sorting list of maps; returning null.",
203: module);
204: return null;
205: }
206: return toSort;
207: }
208:
209: /**
210: * Assuming outerMap not null; if null will throw a NullPointerException
211: */
212: public static Map getMapFromMap(Map outerMap, Object key) {
213: Map innerMap = (Map) outerMap.get(key);
214: if (innerMap == null) {
215: innerMap = FastMap.newInstance();
216: outerMap.put(key, innerMap);
217: }
218: return innerMap;
219: }
220:
221: /**
222: * Assuming outerMap not null; if null will throw a NullPointerException
223: */
224: public static List getListFromMap(Map outerMap, Object key) {
225: List innerList = (List) outerMap.get(key);
226: if (innerList == null) {
227: innerList = FastList.newInstance();
228: outerMap.put(key, innerList);
229: }
230: return innerList;
231: }
232:
233: /**
234: * Assuming theMap not null; if null will throw a NullPointerException
235: */
236: public static void addToBigDecimalInMap(Map theMap, Object mapKey,
237: BigDecimal addNumber) {
238: if (addNumber == null || ZERO_BD.equals(addNumber)) {
239: return;
240: }
241: Object currentNumberObj = theMap.get(mapKey);
242: BigDecimal currentNumber = null;
243: if (currentNumberObj == null) {
244: currentNumber = ZERO_BD;
245: } else if (currentNumberObj instanceof BigDecimal) {
246: currentNumber = (BigDecimal) currentNumberObj;
247: } else if (currentNumberObj instanceof Double) {
248: currentNumber = new BigDecimal(((Double) currentNumberObj)
249: .doubleValue());
250: } else if (currentNumberObj instanceof Long) {
251: currentNumber = new BigDecimal(((Long) currentNumberObj)
252: .longValue());
253: } else {
254: throw new IllegalArgumentException(
255: "In addToBigDecimalInMap found a Map value of a type not supported: "
256: + currentNumberObj.getClass().getName());
257: }
258:
259: currentNumber = currentNumber.add(addNumber);
260: theMap.put(mapKey, currentNumber);
261: }
262:
263: public static Object removeFirst(List lst) {
264: return lst.remove(0);
265: }
266:
267: /**
268: * Create a list from passed objX parameters
269: * @return The resulting List
270: */
271: public static List toList(Object obj1) {
272: List list = new ArrayList(1);
273:
274: list.add(obj1);
275: return list;
276: }
277:
278: /**
279: * Create a list from passed objX parameters
280: * @return The resulting List
281: */
282: public static List toList(Object obj1, Object obj2) {
283: List list = new ArrayList(2);
284:
285: list.add(obj1);
286: list.add(obj2);
287: return list;
288: }
289:
290: /**
291: * Create a list from passed objX parameters
292: * @return The resulting List
293: */
294: public static List toList(Object obj1, Object obj2, Object obj3) {
295: List list = new ArrayList(3);
296:
297: list.add(obj1);
298: list.add(obj2);
299: list.add(obj3);
300: return list;
301: }
302:
303: /**
304: * Create a list from passed objX parameters
305: * @return The resulting List
306: */
307: public static List toList(Object obj1, Object obj2, Object obj3,
308: Object obj4) {
309: List list = new ArrayList(4);
310:
311: list.add(obj1);
312: list.add(obj2);
313: list.add(obj3);
314: list.add(obj4);
315: return list;
316: }
317:
318: /**
319: * Create a list from passed objX parameters
320: * @return The resulting List
321: */
322: public static List toList(Object obj1, Object obj2, Object obj3,
323: Object obj4, Object obj5) {
324: List list = new ArrayList(5);
325:
326: list.add(obj1);
327: list.add(obj2);
328: list.add(obj3);
329: list.add(obj4);
330: list.add(obj5);
331: return list;
332: }
333:
334: /**
335: * Create a list from passed objX parameters
336: * @return The resulting List
337: */
338: public static List toList(Object obj1, Object obj2, Object obj3,
339: Object obj4, Object obj5, Object obj6) {
340: List list = new ArrayList(6);
341:
342: list.add(obj1);
343: list.add(obj2);
344: list.add(obj3);
345: list.add(obj4);
346: list.add(obj5);
347: list.add(obj6);
348: return list;
349: }
350:
351: public static List toList(Collection collection) {
352: if (collection == null)
353: return null;
354: if (collection instanceof List) {
355: return (List) collection;
356: } else {
357: return new ArrayList(collection);
358: }
359: }
360:
361: public static List toListArray(Object[] data) {
362: if (data == null) {
363: return null;
364: }
365: List list = new ArrayList(data.length);
366: for (int i = 0; i < data.length; i++) {
367: list.add(data[i]);
368: }
369: return list;
370: }
371:
372: public static long toLong(Object value) {
373: if (value != null) {
374: if (value instanceof Long) {
375: return ((Long) value).longValue();
376: } else if (value instanceof String) {
377: return Long.parseLong((String) value);
378: }
379: }
380: return 0;
381: }
382:
383: /**
384: * Returns a double from value, where value could either be a Double or a String
385: * @param value
386: * @return
387: */
388: public static double toDouble(Object value) {
389: if (value != null) {
390: if (value instanceof Double) {
391: return ((Double) value).doubleValue();
392: } else if (value instanceof String) {
393: return Double.parseDouble((String) value);
394: }
395: }
396: return 0.0;
397: }
398:
399: /**
400: * Adds value to the key entry in theMap, or creates a new one if not already there
401: * @param theMap
402: * @param key
403: * @param value
404: */
405: public static void addToDoubleInMap(Map theMap, Object key,
406: Double value) {
407: Double curValue = (Double) theMap.get(key);
408: if (curValue != null) {
409: theMap.put(key, new Double(curValue.doubleValue()
410: + value.doubleValue()));
411: } else {
412: theMap.put(key, value);
413: }
414: }
415:
416: /**
417: * Parse a locale string Locale object
418: * @param localeString The locale string (en_US)
419: * @return Locale The new Locale object or null if no valid locale can be interpreted
420: */
421: public static Locale parseLocale(String localeString) {
422: if (localeString == null || localeString.length() == 0) {
423: return null;
424: }
425:
426: Locale locale = null;
427: if (localeString.length() == 2) {
428: // two letter language code
429: locale = new Locale(localeString);
430: } else if (localeString.length() == 5) {
431: // positions 0-1 language, 3-4 are country
432: String language = localeString.substring(0, 2);
433: String country = localeString.substring(3, 5);
434: locale = new Locale(language, country);
435: } else if (localeString.length() > 6) {
436: // positions 0-1 language, 3-4 are country, 6 and on are special extensions
437: String language = localeString.substring(0, 2);
438: String country = localeString.substring(3, 5);
439: String extension = localeString.substring(6);
440: locale = new Locale(language, country, extension);
441: } else {
442: Debug
443: .logWarning(
444: "Do not know what to do with the localeString ["
445: + localeString
446: + "], should be length 2, 5, or greater than 6, returning null",
447: module);
448: }
449:
450: return locale;
451: }
452:
453: /** The input can be a String, Locale, or even null and a valid Locale will always be returned; if nothing else works, returns the default locale.
454: * @param localeObject An Object representing the locale
455: */
456: public static Locale ensureLocale(Object localeObject) {
457: if (localeObject != null && localeObject instanceof String) {
458: localeObject = UtilMisc.parseLocale((String) localeObject);
459: }
460: if (localeObject != null && localeObject instanceof Locale) {
461: return (Locale) localeObject;
462: }
463: return Locale.getDefault();
464: }
465:
466: public static List availableLocaleList = null;
467:
468: /** Returns a List of available locales sorted by display name */
469: public static List availableLocales() {
470: if (availableLocaleList == null) {
471: synchronized (UtilMisc.class) {
472: if (availableLocaleList == null) {
473: TreeMap localeMap = new TreeMap();
474: String localesString = UtilProperties
475: .getPropertyValue("general",
476: "locales.available");
477: if (localesString != null
478: && localesString.length() > 0) { // check if available locales need to be limited according general.properties file
479: int end = -1;
480: int start = 0;
481: for (int i = 0; start < localesString.length(); i++) {
482: end = localesString.indexOf(",", start);
483: if (end == -1) {
484: end = localesString.length();
485: }
486: Locale curLocale = UtilMisc
487: .ensureLocale(localesString
488: .substring(start, end));
489: localeMap.put(curLocale.getDisplayName(),
490: curLocale);
491: start = end + 1;
492: }
493: } else {
494: Locale[] locales = Locale.getAvailableLocales();
495: for (int i = 0; i < locales.length
496: && locales[i] != null; i++) {
497: localeMap.put(locales[i].getDisplayName(),
498: locales[i]);
499: }
500: }
501: availableLocaleList = new LinkedList(localeMap
502: .values());
503: }
504: }
505: }
506: return availableLocaleList;
507: }
508:
509: /** This is meant to be very quick to create and use for small sized maps, perfect for how we usually use UtilMisc.toMap */
510: protected static class SimpleMap implements Map,
511: java.io.Serializable {
512: protected Map realMapIfNeeded = null;
513:
514: String[] names;
515: Object[] values;
516:
517: public SimpleMap() {
518: names = new String[0];
519: values = new Object[0];
520: }
521:
522: public SimpleMap(String name1, Object value1) {
523: names = new String[1];
524: values = new Object[1];
525: this .names[0] = name1;
526: this .values[0] = value1;
527: }
528:
529: public SimpleMap(String name1, Object value1, String name2,
530: Object value2) {
531: names = new String[2];
532: values = new Object[2];
533: this .names[0] = name1;
534: this .values[0] = value1;
535: this .names[1] = name2;
536: this .values[1] = value2;
537: }
538:
539: public SimpleMap(String name1, Object value1, String name2,
540: Object value2, String name3, Object value3) {
541: names = new String[3];
542: values = new Object[3];
543: this .names[0] = name1;
544: this .values[0] = value1;
545: this .names[1] = name2;
546: this .values[1] = value2;
547: this .names[2] = name3;
548: this .values[2] = value3;
549: }
550:
551: public SimpleMap(String name1, Object value1, String name2,
552: Object value2, String name3, Object value3,
553: String name4, Object value4) {
554: names = new String[4];
555: values = new Object[4];
556: this .names[0] = name1;
557: this .values[0] = value1;
558: this .names[1] = name2;
559: this .values[1] = value2;
560: this .names[2] = name3;
561: this .values[2] = value3;
562: this .names[3] = name4;
563: this .values[3] = value4;
564: }
565:
566: protected void makeRealMap() {
567: realMapIfNeeded = FastMap.newInstance();
568: for (int i = 0; i < names.length; i++) {
569: realMapIfNeeded.put(names[i], values[i]);
570: }
571: this .names = null;
572: this .values = null;
573: }
574:
575: public void clear() {
576: if (realMapIfNeeded != null) {
577: realMapIfNeeded.clear();
578: } else {
579: realMapIfNeeded = FastMap.newInstance();
580: names = null;
581: values = null;
582: }
583: }
584:
585: public boolean containsKey(Object obj) {
586: if (realMapIfNeeded != null) {
587: return realMapIfNeeded.containsKey(obj);
588: } else {
589: for (int i = 0; i < names.length; i++) {
590: if (obj == null && names[i] == null)
591: return true;
592: if (names[i] != null && names[i].equals(obj))
593: return true;
594: }
595: return false;
596: }
597: }
598:
599: public boolean containsValue(Object obj) {
600: if (realMapIfNeeded != null) {
601: return realMapIfNeeded.containsValue(obj);
602: } else {
603: for (int i = 0; i < names.length; i++) {
604: if (obj == null && values[i] == null)
605: return true;
606: if (values[i] != null && values[i].equals(obj))
607: return true;
608: }
609: return false;
610: }
611: }
612:
613: public java.util.Set entrySet() {
614: if (realMapIfNeeded != null) {
615: return realMapIfNeeded.entrySet();
616: } else {
617: this .makeRealMap();
618: return realMapIfNeeded.entrySet();
619: }
620: }
621:
622: public Object get(Object obj) {
623: if (realMapIfNeeded != null) {
624: return realMapIfNeeded.get(obj);
625: } else {
626: for (int i = 0; i < names.length; i++) {
627: if (obj == null && names[i] == null)
628: return values[i];
629: if (names[i] != null && names[i].equals(obj))
630: return values[i];
631: }
632: return null;
633: }
634: }
635:
636: public boolean isEmpty() {
637: if (realMapIfNeeded != null) {
638: return realMapIfNeeded.isEmpty();
639: } else {
640: if (this .names.length == 0)
641: return true;
642: return false;
643: }
644: }
645:
646: public java.util.Set keySet() {
647: if (realMapIfNeeded != null) {
648: return realMapIfNeeded.keySet();
649: } else {
650: this .makeRealMap();
651: return realMapIfNeeded.keySet();
652: }
653: }
654:
655: public Object put(Object obj, Object obj1) {
656: if (realMapIfNeeded != null) {
657: return realMapIfNeeded.put(obj, obj1);
658: } else {
659: this .makeRealMap();
660: return realMapIfNeeded.put(obj, obj1);
661: }
662: }
663:
664: public void putAll(java.util.Map map) {
665: if (realMapIfNeeded != null) {
666: realMapIfNeeded.putAll(map);
667: } else {
668: this .makeRealMap();
669: realMapIfNeeded.putAll(map);
670: }
671: }
672:
673: public Object remove(Object obj) {
674: if (realMapIfNeeded != null) {
675: return realMapIfNeeded.remove(obj);
676: } else {
677: this .makeRealMap();
678: return realMapIfNeeded.remove(obj);
679: }
680: }
681:
682: public int size() {
683: if (realMapIfNeeded != null) {
684: return realMapIfNeeded.size();
685: } else {
686: return this .names.length;
687: }
688: }
689:
690: public java.util.Collection values() {
691: if (realMapIfNeeded != null) {
692: return realMapIfNeeded.values();
693: } else {
694: this .makeRealMap();
695: return realMapIfNeeded.values();
696: }
697: }
698:
699: public String toString() {
700: if (realMapIfNeeded != null) {
701: return realMapIfNeeded.toString();
702: } else {
703: StringBuffer outString = new StringBuffer("{");
704: for (int i = 0; i < names.length; i++) {
705: if (i > 0)
706: outString.append(',');
707: outString.append('{');
708: outString.append(names[i]);
709: outString.append(',');
710: outString.append(values[i]);
711: outString.append('}');
712: }
713: outString.append('}');
714: return outString.toString();
715: }
716: }
717:
718: public int hashCode() {
719: if (realMapIfNeeded != null) {
720: return realMapIfNeeded.hashCode();
721: } else {
722: int hashCode = 0;
723: for (int i = 0; i < names.length; i++) {
724: //note that this calculation is done based on the calc specified in the Java java.util.Map interface
725: int tempNum = (names[i] == null ? 0 : names[i]
726: .hashCode())
727: ^ (values[i] == null ? 0 : values[i]
728: .hashCode());
729: hashCode += tempNum;
730: }
731: return hashCode;
732: }
733: }
734:
735: public boolean equals(Object obj) {
736: if (realMapIfNeeded != null) {
737: return realMapIfNeeded.equals(obj);
738: } else {
739: Map mapObj = (Map) obj;
740:
741: //first check the size
742: if (mapObj.size() != names.length)
743: return false;
744:
745: //okay, same size, now check each entry
746: for (int i = 0; i < names.length; i++) {
747: //first check the name
748: if (!mapObj.containsKey(names[i]))
749: return false;
750:
751: //if that passes, check the value
752: Object mapValue = mapObj.get(names[i]);
753: if (mapValue == null) {
754: if (values[i] != null)
755: return false;
756: } else {
757: if (!mapValue.equals(values[i]))
758: return false;
759: }
760: }
761:
762: return true;
763: }
764: }
765: }
766: }
|