Coverage Report - org.as3collections.utils.MapUtil
 
Classes in this File Line Coverage Branch Coverage Complexity
MapUtil
90%
49/54
N/A
0
 
 1  
 /*
 2  
  * Licensed under the MIT License
 3  
  * 
 4  
  * Copyright 2010 (c) Flávio Silva, http://flsilva.com
 5  
  *
 6  
  * Permission is hereby granted, free of charge, to any person
 7  
  * obtaining a copy of this software and associated documentation
 8  
  * files (the "Software"), to deal in the Software without
 9  
  * restriction, including without limitation the rights to use,
 10  
  * copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  
  * copies of the Software, and to permit persons to whom the
 12  
  * Software is furnished to do so, subject to the following
 13  
  * conditions:
 14  
  *
 15  
  * The above copyright notice and this permission notice shall be
 16  
  * included in all copies or substantial portions of the Software.
 17  
  *
 18  
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 19  
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 20  
  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 21  
  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 22  
  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 23  
  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 24  
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 25  
  * OTHER DEALINGS IN THE SOFTWARE.
 26  
  * 
 27  
  * http://www.opensource.org/licenses/mit-license.php
 28  
  */
 29  
 
 30  1
 package org.as3collections.utils
 31  
 {
 32  
         import org.as3collections.ICollection;
 33  
         import org.as3collections.IIterator;
 34  
         import org.as3collections.IListMap;
 35  
         import org.as3collections.IMap;
 36  
         import org.as3collections.IMapEntry;
 37  
         import org.as3collections.ISortedMap;
 38  
         import org.as3collections.maps.TypedListMap;
 39  
         import org.as3collections.maps.TypedMap;
 40  
         import org.as3collections.maps.TypedSortedMap;
 41  
         import org.as3utils.BooleanUtil;
 42  
         import org.as3utils.NumberUtil;
 43  
         import org.as3utils.ReflectionUtil;
 44  
 
 45  
         import flash.errors.IllegalOperationError;
 46  
 
 47  
         /**
 48  
          * A utility class to work with implementations of the <code>IMap</code> interface.
 49  
          * 
 50  
          * @author Flávio Silva
 51  
          */
 52  
         public class MapUtil
 53  
         {
 54  
                 /**
 55  
                  * <code>MapUtil</code> is a static class and shouldn't be instantiated.
 56  
                  * 
 57  
                  * @throws         IllegalOperationError         <code>MapUtil</code> is a static class and shouldn't be instantiated.
 58  
                  */
 59  
                 public function MapUtil()
 60  1
                 {
 61  1
                         throw new IllegalOperationError("MapUtil is a static class and shouldn't be instantiated.");
 62  
                 }
 63  
                 
 64  
                 /**
 65  
                  * Performs an arbitrary, specific evaluation of equality between this object and the <code>other</code> object.
 66  
                  * If one of the maps or both maps are <code>null</code> it will be returned <code>false</code>.
 67  
                  * <p>Two different objects are considered equal if:</p>
 68  
                  * <p>
 69  
                  * <ul><li>object A and object B are instances of the same class (i.e. if they have <b>exactly</b> the same type)</li>
 70  
                  * <li>object A contains all mappings of object B</li>
 71  
                  * <li>object B contains all mappings of object A</li>
 72  
                  * <li>mappings have exactly the same order</li>
 73  
                  * </ul></p>
 74  
                  * <p>This implementation <b>takes care</b> of the order of the mappings in the maps.
 75  
                  * So, for two maps are equal the order of entries returned by the iterator object must be equal.</p>
 76  
                  * 
 77  
                  * @param          map1         the first map.
 78  
                  * @param          map2         the second map.
 79  
                  * @return         <code>true</code> if the arbitrary evaluation considers the objects equal.
 80  
                  */
 81  
                 public static function equalConsideringOrder(map1:IMap, map2:IMap): Boolean
 82  
                 {
 83  1
                         if (!map1 || !map2) return false;
 84  1
                         if (map1 == map2) return true;
 85  
                         
 86  1
                         if (!ReflectionUtil.classPathEquals(map1, map2)) return false;
 87  1
                         if (map1.size() != map2.size()) return false;
 88  
                         
 89  1
                         var itEntryList1:IIterator = map1.entryCollection().iterator();
 90  1
                         var itEntryList2:IIterator = map2.entryCollection().iterator();
 91  
                         var mapEntry1:IMapEntry;
 92  
                         var mapEntry2:IMapEntry;
 93  
                         
 94  1
                         while (itEntryList1.hasNext())
 95  
                         {
 96  1
                                 mapEntry1 = itEntryList1.next();
 97  1
                                 mapEntry2 = itEntryList2.next();
 98  
                                 
 99  1
                                 if (!mapEntry1.equals(mapEntry2)) return false;
 100  
                         }
 101  
                         
 102  1
                         return true;
 103  
                 }
 104  
                 
 105  
                 /**
 106  
                  * Performs an arbitrary, specific evaluation of equality between this object and the <code>other</code> object.
 107  
                  * If one of the maps or both maps are <code>null</code> it will be returned <code>false</code>.
 108  
                  * <p>Two different objects are considered equal if:</p>
 109  
                  * <p>
 110  
                  * <ul><li>object A and object B are instances of the same class (i.e. if they have <b>exactly</b> the same type)</li>
 111  
                  * <li>object A contains all mappings of object B</li>
 112  
                  * <li>object B contains all mappings of object A</li>
 113  
                  * </ul></p>
 114  
                  * <p>This implementation <b>does not takes care</b> of the order of the mappings in the map.</p>
 115  
                  * 
 116  
                  * @param          map1         the first map.
 117  
                  * @param          map2         the second map.
 118  
                  * @return         <code>true</code> if the arbitrary evaluation considers the objects equal.
 119  
                  */
 120  
                 public static function equalNotConsideringOrder(map1:IMap, map2:IMap): Boolean
 121  
                 {
 122  1
                         if (!map1 || !map2) return false;
 123  1
                         if (map1 == map2) return true;
 124  
                         
 125  1
                         if (!ReflectionUtil.classPathEquals(map1, map2)) return false;
 126  1
                         if (map1.size() != map2.size()) return false;
 127  
                         
 128  1
                         var itMap1:IIterator = map1.entryCollection().iterator();
 129  1
                         var entryListMap2:ICollection = map2.entryCollection();
 130  
                         
 131  
                         // because maps has same size
 132  
                         // it's not necessary to perform bidirectional validation
 133  
                         // i.e. if map1 contains all entries of map2
 134  
                         // consequently map2 contains all entries of map1
 135  1
                         while (itMap1.hasNext())
 136  
                         {
 137  1
                                 if (!entryListMap2.contains(itMap1.next())) return false;
 138  
                         }
 139  
                         
 140  1
                         return true;
 141  
                 }
 142  
                 
 143  
                 /**
 144  
                  * Feeds argument <code>map</code> with argument <code>list</code>.
 145  
                  * <p>The name of the nodes become keys and the values of the nodes become values of the <code>IMap</code> object.</p>
 146  
                  * 
 147  
                  * @example
 148  
                  * 
 149  
                  * <listing version="3.0">
 150  
                  * import org.as3collections.maps.HashMap;
 151  
                  * import org.as3collections.utils.MapUtil;
 152  
                  * 
 153  
                  * var map:IMap = new HashMap();
 154  
                  * var xml:XML = &lt;index&gt;&lt;key1&gt;value1&lt;/key1&gt;&lt;key2&gt;value2&lt;/key2&gt;&lt;/index&gt;;
 155  
                  * 
 156  
                  * MapUtil.feedMapFromXmlList(map, xml.children());
 157  
                  * 
 158  
                  * trace(map); // [key1=value1,key2=value2]
 159  
                  * </listing>
 160  
                  * 
 161  
                  * @param          map                         the map to be fed.
 162  
                  * @param          list                         the list to retrieve entries.
 163  
                  * @param          typeCoercion         if <code>true</code> performs a type coercion to Boolean if some String is "true" or "false", or a type coercion to Number if some String is a Number <code>(i.e. !isNaN(Number(string)) == true)</code>.
 164  
                  */
 165  
                 public static function feedMapWithXmlList(map:IMap, list:XMLList, typeCoercion:Boolean = true): void
 166  
                 {
 167  1
                         if (!map) throw new ArgumentError("Argument <map> must not be null.");
 168  1
                         if (!list) return;
 169  
                         
 170  
                         var nodeName:*;
 171  
                         var nodeValue:*;
 172  
                         
 173  1
                         for each (var node:XML in list)
 174  
                         {
 175  1
                                 nodeName = node.localName();
 176  
                                 
 177  1
                                 if (node.hasComplexContent())
 178  
                                 {
 179  0
                                         if (!isNaN(node.children().length()) && node.children().length() > 0)
 180  
                                         {
 181  0
                                                 nodeValue = feedMapWithXmlList(map, node.children(), typeCoercion);
 182  
                                         }
 183  
                                         else
 184  
                                         {
 185  0
                                                 nodeValue = node;
 186  
                                         }
 187  
                                 }
 188  
                                 else
 189  
                                 {
 190  1
                                         nodeValue = node.toString();
 191  
                                 }
 192  
                                 
 193  1
                                 if (typeCoercion)
 194  
                                 {
 195  1
                                         if (BooleanUtil.isBooleanString(nodeName))
 196  
                                         {
 197  0
                                                 nodeName = BooleanUtil.string2Boolean(nodeName);
 198  
                                         }
 199  1
                                         else if (NumberUtil.isNumber(Number(nodeName)))
 200  
                                         {
 201  0
                                                 nodeName = Number(nodeName);
 202  
                                         }
 203  
                                         
 204  1
                                         if (BooleanUtil.isBooleanString(nodeValue))
 205  
                                         {
 206  1
                                                 nodeValue = BooleanUtil.string2Boolean(nodeValue);
 207  
                                         }
 208  1
                                         else if (NumberUtil.isNumber(Number(nodeValue)))
 209  
                                         {
 210  1
                                                 nodeValue = Number(nodeValue);
 211  
                                         }
 212  
                                 }
 213  
                                 
 214  1
                                 map.put(nodeName, nodeValue);
 215  
                         }
 216  1
                 }
 217  
                 
 218  
                 /**
 219  
                  * Returns a new <code>TypedMap</code> with the <code>wrapMap</code> argument wrapped.
 220  
                  * 
 221  
                  * @param          wrapMap         the target map to be wrapped by the <code>TypedMap</code>.
 222  
                  * @param         typeKeys        the type of the keys allowed by the returned <code>TypedMap</code>.
 223  
                  * @param         typeValues        the type of the values allowed by the returned <code>TypedMap</code>.
 224  
                  * @throws         ArgumentError          if the <code>wrapMap</code> argument is <code>null</code>.
 225  
                  * @throws         ArgumentError          if the <code>typeKeys</code> argument is <code>null</code>.
 226  
                  * @throws         ArgumentError          if the <code>typeValues</code> argument is <code>null</code>.
 227  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the types of one or more keys or values in the <code>wrapMap</code> argument are incompatible with the <code>typeKeys</code> or <code>typeValues</code> argument.
 228  
                  * @return         a new <code>TypedMap</code> with the <code>wrapMap</code> argument wrapped.
 229  
                  */
 230  
                 public static function getTypedMap(wrapMap:IMap, typeKeys:*, typeValues:*): TypedMap
 231  
                 {
 232  1
                         return new TypedMap(wrapMap, typeKeys, typeValues);
 233  
                 }
 234  
                 
 235  
                 /**
 236  
                  * Returns a new <code>TypedListMap</code> with the <code>wrapMap</code> argument wrapped.
 237  
                  * 
 238  
                  * @param          wrapMap         the target map to be wrapped by the <code>TypedListMap</code>.
 239  
                  * @param         typeKeys        the type of the keys allowed by the returned <code>TypedListMap</code>.
 240  
                  * @param         typeValues        the type of the values allowed by the returned <code>TypedListMap</code>.
 241  
                  * @throws         ArgumentError          if the <code>wrapMap</code> argument is <code>null</code>.
 242  
                  * @throws         ArgumentError          if the <code>typeKeys</code> argument is <code>null</code>.
 243  
                  * @throws         ArgumentError          if the <code>typeValues</code> argument is <code>null</code>.
 244  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the types of one or more keys or values in the <code>wrapMap</code> argument are incompatible with the <code>typeKeys</code> or <code>typeValues</code> argument.
 245  
                  * @return         a new <code>TypedListMap</code> with the <code>wrapMap</code> argument wrapped.
 246  
                  */
 247  
                 public static function getTypedListMap(wrapMap:IListMap, typeKeys:*, typeValues:*): TypedListMap
 248  
                 {
 249  1
                         return new TypedListMap(wrapMap, typeKeys, typeValues);
 250  
                 }
 251  
 
 252  
                 /**
 253  
                  * Returns a new <code>TypedSortedMap</code> with the <code>wrapMap</code> argument wrapped.
 254  
                  * 
 255  
                  * @param          wrapMap         the target map to be wrapped by the <code>TypedSortedMap</code>.
 256  
                  * @param         typeKeys        the type of the keys allowed by the returned <code>TypedSortedMap</code>.
 257  
                  * @param         typeValues        the type of the values allowed by the returned <code>TypedSortedMap</code>.
 258  
                  * @throws         ArgumentError          if the <code>wrapMap</code> argument is <code>null</code>.
 259  
                  * @throws         ArgumentError          if the <code>typeKeys</code> argument is <code>null</code>.
 260  
                  * @throws         ArgumentError          if the <code>typeValues</code> argument is <code>null</code>.
 261  
                  * @throws         org.as3coreaddendum.errors.ClassCastError                  if the types of one or more keys or values in the <code>wrapMap</code> argument are incompatible with the <code>typeKeys</code> or <code>typeValues</code> argument.
 262  
                  * @return         a new <code>TypedSortedMap</code> with the <code>wrapMap</code> argument wrapped.
 263  
                  */
 264  
                 public static function getTypedSortedMap(wrapMap:ISortedMap, typeKeys:*, typeValues:*): TypedSortedMap
 265  
                 {
 266  1
                         return new TypedSortedMap(wrapMap, typeKeys, typeValues);
 267  
                 }
 268  
                 
 269  
                 /**
 270  
                  * Returns the string representation of the <code>map</code> argument.
 271  
                  * 
 272  
                  * @param          map the target map.
 273  
                  * @return         the string representation of the target map.
 274  
                   */
 275  
                 public static function toString(map:IMap): String 
 276  
                 {
 277  1
                         var s:String = "[";
 278  1
                         var it:IIterator = map.iterator();
 279  
                         var value        :*;
 280  
                         
 281  1
                         while (it.hasNext())
 282  
                         {
 283  1
                                 value         = it.next();
 284  
                                 
 285  1
                                 s                 += it.pointer() + "=" + value;
 286  1
                                 if (it.hasNext()) s += ",";
 287  
                         }
 288  
                         
 289  1
                         s += "]";
 290  
                         
 291  1
                         return s;
 292  
                 }
 293  
 
 294  
         }
 295  
 
 296  
 }