Package ariba.util.core

Source Code of ariba.util.core.WrappedEnumeration

/*
    Copyright (c) 1996-2010 Ariba, Inc.
    All rights reserved. Patents pending.

    $Id: //ariba/platform/util/core/ariba/util/core/MapUtil.java#31 $

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

*/

package ariba.util.core;


import ariba.util.io.DeserializationException;
import ariba.util.io.Deserializer;
import ariba.util.io.Serializer;
import ariba.util.log.Log;
import ariba.util.formatter.DateFormatter;
import ariba.util.formatter.IntegerFormatter;
import ariba.util.formatter.DoubleFormatter;
import ariba.util.formatter.LongFormatter;
import ariba.util.formatter.BigDecimalFormatter;
import ariba.util.formatter.BooleanFormatter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Collection;
import java.math.BigDecimal;

/**
    Map Utilities. These are helper functions for dealing with
    maps.

    @aribaapi documented
*/
public final class MapUtil
{

    /* prevent people from creating this class */
    private MapUtil ()
    {
    }


    //-------------------------------------------------------------
    //----- UTILITY METHODS TO RETRIEVE THE DEFAULT MAP IMPL. -----
    //-------------------------------------------------------------

    /**
        Constructs an  empty Map. The Map will grow on demand
        as more elements are added.
        @return new empty Map
        @aribaapi documented
    */
    public static <K,V> Map<K,V> map ()
    {
        return new HashMap<K,V>(2); // OK
    }

    /**
        Helper method to clone a map
        @param m the map to clone
        @return a new map of the same type

        @aribaapi documented
    */
    @SuppressWarnings("unchecked")
    public static <K,V> Map<K,V> cloneMap (Map<K,V> m)
    {
        return (Map<K,V>)ClassUtil.clone(m);
    }

    /**
        Constructs a Map capable of holding a specified number
        of elements. <p/>

        To construct a type-safe <code>Map</code>:<ul>
        <li><code>Map&lt;K,V> typesafe = MapUtil.map()</code>
        </ul>
        For a raw <code>Map</code>:<ul>
        <li><code>Map raw = MapUtil.map()</code>
        </ul>
        There will be no compile warnings either way.

        @param initialCapacity the number of elements this Map
        is capable of holding before needing to grow.
        @return new empty Map with given initial capacity
        @aribaapi documented
    */
    public static <K,V> Map<K,V> map (int initialCapacity)
    {
        return new HashMap<K,V>(initialCapacity); // OK
    }


    /**
        Creates new Map with the same contents as the given Map.

        To construct a type-safe <code>Map</code>:<ul>
        <li><code>Map&lt;K,V> typesafe = MapUtil.map()</code>
        </ul>
        For a raw <code>Map</code>:<ul>
        <li><code>Map raw = MapUtil.map()</code>
        </ul>
        There will be no compile warnings either way.

        @param source source Map
        @return new Map with same contents as <code>source</code>
        @aribaapi documented
    */
    public static <K,V> Map<K,V> map (Map<? extends K, ? extends V> source)
    {
        return new HashMap<K,V>(source); // OK
    }

    //----------------------------------------------------
    //----- UTILITY METHODS TO RETRIEVE A SORTED MAP -----
    //----------------------------------------------------

    /**
        Creates an empty SortedMap
        @return new empty SortedMap implementation
        @see java.util.SortedMap
        @aribaapi documented
    */
    public static <K,V> SortedMap<K,V> sortedMap ()
    {
        return new TreeMap<K,V>();
    }

    /**
        Creates an empty SortedMap
        @param comparator the comparator that will be used to sort this map
        @return new empty SortedMap implementation
        @see java.util.SortedMap
        @aribaapi documented
    */
    public static <K,V> SortedMap<K,V> sortedMap (Comparator<K> comparator)
    {
        return new TreeMap<K,V>(comparator);
    }

    /**
        Creates a new SortedMap with the same content as the given SortedMap
        @param source the sorted map whose mappings are to be placed in this map
        @return new map containing the same mappings as the given SortedMap
        @see java.util.SortedMap
        @aribaapi documented
    */
    public static <K,V> SortedMap<K,V> sortedMap (
        SortedMap<? extends K, ? extends V> source)
    {
        return new TreeMap<K,V>(source);
    }

    /**
        Copies the contents of a Map into a SortedMap. If there is a Map within this Map,
        then it will recurse to copy that Map into a SortedMap. If there is a List, then
        ListUtil.copyAndSortMapInList is called for processing.
        @param source the map whose mappings are to be copied into a SortedMap
        @return new SortedMap containing the same mappings as the given Map
        @see java.util.SortedMap
        @see ariba.util.core.ListUtil
        @aribaapi documented
     */
    public static SortedMap copyAndSortMap (Map<String,Object> source)
    {
        SortedMap sortedMap = MapUtil.sortedMap();
       
        if (MapUtil.nullOrEmptyMap(source)) {
            return sortedMap;
        }
       
        // Iterate through the source Map and copy its contents to the SortedMap.
        for (Map.Entry<String,Object> e : source.entrySet()) {
            // If there are maps within maps, then recurse through them and convert them
            // into a SortedMap also.
            String mapKey = e.getKey();
            Object mapValue = e.getValue();

            if (mapValue instanceof Map) {
                SortedMap sm = MapUtil.copyAndSortMap((Map)mapValue);
                sortedMap.put(mapKey, sm);
            }
            else if (mapValue instanceof List) {
                // A map can contain a List which contains a Map. We need to convert these
                // maps into sorted maps as well.
                List list = ListUtil.copyAndSortMapInList((List)mapValue);
                sortedMap.put(mapKey, list);
            }
            else {
                sortedMap.put(mapKey, mapValue);
            }
        }
       
        return sortedMap;
    }

    /**
        Returns a List containing the Map's keys. If the Map
        contains no keys, return an empty List object.

        @param ht the table to return keys from
        @return the List object mentioned above.
        @aribaapi documented
    */
    public static <T> List<T> keysList (Map<? extends T, ?> ht)
    {
        return ListUtil.<T>arrayToList(keysArray(ht));
    }



    /**
        Returns a List containing the Map's elements. If the map
        containes no elements, an empty List object is returned.
        @param ht the Map whose elements are to be returned in the
        returned list.
        @return the List object mentioned above.
        @aribaapi documented
    */
    public static <T> List<T> elementsList (Map<?,? extends T> ht)
    {
        return ListUtil.<T>arrayToList(elementsArray(ht));
    }


    /**
        Returns an Object array containing the Map's keys. If the
        Map contains no keys, an empty array is returned.
        @param ht the table to return keys from
        @return the Object array above mentioned.
        @aribaapi documented
    */
    public static <T> T[] keysArray (Map<? extends T,?> ht)
    {
        return ht.keySet().toArray((T[])new Object[0]);
    }

    /**
        Returns an Object array containing the Map's elements.
        @return the Object array mentioned above. If there the map contains
        no elements, an empty array is returned.
        @param ht the table to return elements from
        @aribaapi documented
    */
    public static <T> T[] elementsArray (Map<?,? extends T> ht)
    {
        Collection<? extends T> values = ht.values();
        return values.toArray((T[])new Object[0]);
    }


    /**
        Finds and removes all occurrences of <b>element</b> from the Map.
        Note that this method is slow -- O(n) -- because it must scan the table
        searching for the element.
        @param ht the Map to modify
        @param element the element to search for.  Map compares elements
        using <b>equals()</b>.

        @return the number of elements removed.
        @aribaapi documented
    */
    public static int removeElement (Map ht, Object element)
    {
        int startingSize = ht.size();
        ht.values().removeAll(ListUtil.list(element));
        return (startingSize-ht.size());
    }

    /**
        Returns whether all list elements are strings
    */
    public static boolean allElementsAreStrings (List<?> v)
    {
        for (int i = v.size()-1; i >= 0; i--) {
            if (!(v.get(i) instanceof String)) {
                return false;
            }
        }
        return true;
    }

    /**
        Determine if a Map is null or empty.

        @param map a map object to check

        @return <b>true</b> if <B>map</B> is null or empty,
        <b>false</b> otherwise
        @aribaapi documented
    */
    public static boolean nullOrEmptyMap (Map<?,?> map)
    {
        return (map == null) || map.isEmpty();
    }

    /**
        Create a Map of Maps from a List. Creates a new
        map where each key is an element from the List
        <B>v</B>. Each element of the new map is itself an empty
        map.

        @param keys a List of items to become keys in created
        Map

        @return a new Map containing each element of keys.
        @aribaapi documented
    */
    public static Map convertListToMap (List keys)
    {
        Map ht = map(keys.size());
        for (int i=0, s=keys.size(); i<s; i++) {
            ht.put(keys.get(i), map());
        }
        return ht;
    }

    /**
        Merges two Maps together. The source map has precedence. <p/>

        The allowed keys and values in <code>source</code> and <code>dest</code>
        are (essentially) <code>Strings</code>, <code>Lists</code> and
        <code>Maps</code>.  After the merge <code>dest</code> can best
        be described as "a union of the entries in itself and in
        <code>source</code>."
        That is any entries in <code>source</code> but not in
        <code>dest</code> will be copied into <code>dest</code>.
        For entries that are in both <code>source</code> and <code>dest</code>: <ul>
        <li> if both entries are <code>Strings</code>, <code>source</code>
             overwrites <code>dest</code>
        <li> if both entries are <code>Lists</code> they are unioned
        <li> if both entries are <code>Maps</code> they are
             {@link #mergeMapIntoMap merged} (hence this method is recursive)
        </ul>
        If the entries in <code>source</code> and <code>dest</code> are not
        the same type, things start to get complicated and are intuitive about
        half the time. For instance if <code>dest</code> contains a
        <code>List</code> and <code>source</code> a <code>String</code>, the
        <code>String</code> in <code>source</code> gets added. (However,
        the opposite situation is not-at-all intuitive.) <p/>

        <b>Important note:</b> the only map modified in this method is
        <code>dest</code>. No sub-maps of <code>dest</code> (or indeed any
        maps of <code>source</code>) are modified. <p/>

        @param source the map to merge into <code>dest</code>
        @param dest the map into which <code>source</code> is to be merged
        @return the destination map
        @aribaapi private
    */
    public static Map mergeMapIntoMap (Map dest, Map source)
    {
        return mergeMapIntoMap(dest, source, false);
    }

    public static Map mergeMapIntoMap (Map dest, Map source,
                                       boolean appendMergeListProperties)
    {

        Iterator i = source.keySet().iterator();

        while (i.hasNext()) {
            Object key = i.next();
            Object sourceValue = source.get(key);
            Object destValue = dest.get(key);
            if (destValue == null) {
                dest.put(key, ListUtil.copyValue(sourceValue));
                continue;
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof Map))
            {
                dest.put(key,
                         mergeMapIntoMap(
                             copyMap((Map)destValue),
                             (Map)sourceValue));
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof List))
            {
                if (allElementsAreStrings((List)sourceValue)) {
                    dest.put(key,
                             mergeMapIntoMap(
                                 copyMap((Map)destValue),
                                 convertListToMap(
                                     (List)sourceValue)));
                }
                else {
                    List sourceVect = ListUtil.copyList((List)sourceValue);
                    if (appendMergeListProperties) {
                        ListUtil.appendAndRemoveIfPresent(sourceVect, destValue);
                    }
                    else {
                        ListUtil.addElementIfAbsent(sourceVect, destValue);
                    }
                    dest.put(key, sourceVect);
                }
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof Map))
            {
                if (allElementsAreStrings((List)destValue)) {
                    dest.put(key,
                             mergeMapIntoMap(
                                 convertListToMap((List)destValue),
                                 (Map)sourceValue));
                }
                else {
                    if (appendMergeListProperties) {
                        ListUtil.appendAndRemoveIfPresent(((List)destValue),
                                                     copyMap((Map)sourceValue));
                    }
                    else {
                        ListUtil.addElementIfAbsent(((List)destValue),
                                                    copyMap((Map)sourceValue));
                    }
                }
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof String))
            {
                Map destValueMap =
                    copyMap((Map)destValue);
                if (destValueMap.get(sourceValue) == null) {
                    ((Map)destValue).put(sourceValue, map());
                }
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof Map))
            {
                Map sourceHash = copyMap((Map)sourceValue);
                if (sourceHash.get(destValue) == null) {
                    sourceHash.put(destValue, map());
                }
                dest.put(key, sourceHash);
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof List))
            {
                if (appendMergeListProperties) {
                    ListUtil.appendAndRemoveIfPresent((List)destValue,
                                                  ListUtil.copyList((List)sourceValue));
                }
                else {
                    ListUtil.addElementsIfAbsent((List)destValue,
                                                 ListUtil.copyList((List)sourceValue));
                }
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof String))
            {
                if (appendMergeListProperties) {
                    ListUtil.appendAndRemoveIfPresent((List)destValue, sourceValue);
                }
                else {
                    ListUtil.addElementIfAbsent((List)destValue, sourceValue);
                }
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof List))
            {
                List sourceVect = ListUtil.copyList((List)sourceValue);
                if (appendMergeListProperties) {
                    ListUtil.appendAndRemoveIfPresent(sourceVect, destValue);
                }
                else {
                    ListUtil.addElementIfAbsent(sourceVect, destValue);
                }
                dest.put(key, sourceVect);
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof String))
            {
                dest.put(key, sourceValue);
            }
        }
        return dest;
    }

    /**
        Merges two Maps together. The source map has precedence. <p/>

        See mergeMapIntoMap. The only addition is that this method attempts to handle
        non-[String,List,Map] objects by overriding objects of one class with objects of the same class.

        For non-String objects, no complex operation (such as adding scalar objects to vectors) are attempted.

        @param source the map to merge into <code>dest</code>
        @param dest the map into which <code>source</code> is to be merged
        @return the destination map
        @aribaapi private
    */
    public static Map mergeMapIntoMapWithObjects (Map dest, Map source)
    {
        return mergeMapIntoMapWithObjects(dest, source, false);
    }

    public static Map mergeMapIntoMapWithObjects (Map dest, Map source, boolean overwriteMismatchedClasses)
    {
        Iterator i = source.keySet().iterator();

        while (i.hasNext()) {
            Object key = i.next();
            Object sourceValue = source.get(key);
            Object destValue = dest.get(key);
            if (destValue == null) {
                dest.put(key, ListUtil.copyValue(sourceValue));
                continue;
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof Map))
            {
                dest.put(key,
                         mergeMapIntoMapWithObjects(
                             copyMap((Map)destValue),
                             (Map)sourceValue, overwriteMismatchedClasses));
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof List))
            {
                if (allElementsAreStrings((List)sourceValue)) {
                    dest.put(key,
                             mergeMapIntoMapWithObjects(
                                 copyMap((Map)destValue),
                                 convertListToMap(
                                     (List)sourceValue), overwriteMismatchedClasses));
                }
                else {
                    List sourceVect = ListUtil.copyList((List)sourceValue);
                    ListUtil.addElementIfAbsent(sourceVect, destValue);
                    dest.put(key, sourceVect);
                }
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof Map))
            {
                if (allElementsAreStrings((List)destValue)) {
                    dest.put(key,
                             mergeMapIntoMapWithObjects(
                                 convertListToMap((List)destValue),
                                 (Map)sourceValue, overwriteMismatchedClasses));
                }
                else {
                    ListUtil.addElementIfAbsent(((List)destValue),
                        copyMap((Map)sourceValue));
                }
            }
            else if ((destValue instanceof Map) &&
                     (sourceValue instanceof String))
            {
                Map destValueMap =
                    copyMap((Map)destValue);
                if (destValueMap.get(sourceValue) == null) {
                    ((Map)destValue).put(sourceValue, map());
                }
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof Map))
            {
                Map sourceHash = copyMap((Map)sourceValue);
                if (sourceHash.get(destValue) == null) {
                    sourceHash.put(destValue, map());
                }
                dest.put(key, sourceHash);
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof List))
            {
                // change related to CR 1-46QA3J
                // we want to overlay the source value onto the dest value
                // and not make a merge, which actually keeps items deleted
                // by the Customer via ABA
                dest.put(key, sourceValue);
            }
            else if ((destValue instanceof List) &&
                     (sourceValue instanceof String))
            {
                ListUtil.addElementIfAbsent((List)destValue, sourceValue);
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof List))
            {
                List sourceVect = ListUtil.copyList((List)sourceValue);
                ListUtil.addElementIfAbsent(sourceVect, destValue);
                dest.put(key, sourceVect);
            }
            else if ((destValue instanceof String) &&
                     (sourceValue instanceof String))
            {
                dest.put(key, sourceValue);
            }
            else if (overwriteMismatchedClasses) {
                dest.put(key, sourceValue);
            }
            else {
                Class destClass = (destValue == null) ? null : destValue.getClass();
                Class sourceClass = (sourceValue == null) ? null : sourceValue.getClass();

                if (destClass == sourceClass) {
                    dest.put(key, sourceValue);
                }
            }
        }
        return dest;
    }

    /**
        Overlays <code>source</code> onto <code>dest</code>. <p/>

        This method has similar behavior to {@link #mergeMapIntoMap} with the
        exception that no merges happen--<code>source</code> is simply written
        on top of <code>dest</code>. That is, every entry in <code>source</code>
        but not in <code>dest</code> is copied into <code>dest</code>.
        For every entry that is in both <code>source</code> and <code>dest</code>
        the <code>source</code> value overwrites the <code>dest</code> value.
        <p/>
        So, in essence this method is alot simpler than {@link #mergeMapIntoMap}.
        <p/>

        @param source the map to merge into <code>dest</code>
        @param dest the map into which <code>source</code> is to be merged
        @return <code>dest</code>
        @aribaapi ariba
    */
    public static Map overlayMapOntoMap (Map dest, Map source)
    {
        for (Iterator iter=source.keySet().iterator(); iter.hasNext(); ) {
            Object key = iter.next();
            Object valueCopy = ListUtil.copyValue(source.get(key));
            dest.put(key, valueCopy);
        }
        return dest;
    }

    /**
        Overwrites the contents of a given Map with the contents
        of another Map.

        @param overriding  the overriding Map
        @param overridden  the Map to be overridden

        @return a new Map that results from the overwriting
        process.

        @aribaapi private
    */
    public static Map overwriteMap (Map overriding,
                                    Map overridden)
    {
            // first make a copy of the one to be overridden
        Map newMap = copyMap(overridden);
        overwriteMapInPlace(overriding, newMap);
        return newMap;
    }

    /**
        A version of overwriteMap that sideeffects the overriden
        Map directly, instead of making a copy to return.

        @aribaapi private
    */
    public static void overwriteMapInPlace (Map overriding,
                                            Map overridden)
    {
        Iterator i = overriding.keySet().iterator();
        while (i.hasNext()) {
            Object key = i.next();
            Object overridingValue = overriding.get(key);
            Object overriddenValue = overridden.get(key);
            if (overridingValue instanceof Map &&
                overriddenValue instanceof Map) {
                    // recurse
                overwriteMapInPlace((Map)overridingValue,
                                    (Map)overriddenValue);
            }
            else {
                    // overwrite the one in overridden
                overridden.put(key, overridingValue);
            }
        }
    }

    /**
        Applies a single deletion or list of  deletions to a map.  This
        is used to implement the deleteProperty AML element.  deletes can be
        either a single string or a list of Objects.

        Returns false if it had any undeletable deletes.

        @aribaapi private
    */
    public static boolean performDeletesOnMap (Object deletes, Map table)
    {
        if (deletes instanceof String) {
            return table.remove(deletes) != null;
        }
        else {
            Assert.that(deletes instanceof List,
                        "Strange type of object to try to delete: %s",
                        deletes);
            List deletesList = (List)deletes;
            boolean returnValue = true;
            for (int i = deletesList.size()-1; i >= 0; i--) {
                if (table.remove(deletesList.get(i)) == null) {
                    returnValue = false;
                }
            }
            return returnValue;
        }
    }

    /**
        Copy a Map.  This method will copy the source map and output
        a destination map.
        For each list or hastable within the source map they will also be
        copied,all other types will be shared.  So for a map of lists or
        maps, this will recurse.

        @param source the source map to copy.
        @return the destination map.
        @aribaapi documented
    */
    public static Map copyMap (Map source)
    {
        Map destination = map(source.size());
        Iterator i = source.keySet().iterator();
        while (i.hasNext()) {
            Object key = i.next();
            Object value = source.get(key);
            destination.put(key, ListUtil.copyValue(value));
        }
        return destination;
    }

    /**
        Determine if the two maps are equal.
        <b>Note:</b> this is different from Map.equals() method because
        this one is recursive.

        @param h1 the first Map
        @param h2 the second Map

        @return <b>true</b> if the two maps are equal, <b>false</b>
        otherwise
        @aribaapi documented
    */
    public static boolean mapEquals (Map h1, Map h2)
    {
        if (h1 == h2) {
            return true;
        }
        if (h1 == null || h2 == null || h1.size() != h2.size()) {
            return false;
        }
        for (Iterator i = h1.keySet().iterator(); i.hasNext();) {
            Object key = i.next();
            Object val2 = h2.get(key);
            Object val1 = h1.get(key);
            if (! SystemUtil.objectEquals(val1, val2)) {
                return false;
            }
        }
        return true;
    }

    /**
        Convenience generic method that merges <code>key</code> and
        <code>value</code> into the supplied <code>map</code>. <p/>

        The semantics are, add <code>value</code> to the list of
        <code>values</code> associated with <code>key</code> in
        <code>map</code>. <p/>

        @param map the map to merge into
        @param key the key
        @param value the value

        @aribaapi ariba
    */
    public static <K,V> void merge (Map<K,List<V>> map, K key, V value)
    {
        List<V> list = map.get(key);
        if (list == null) {
            list = ListUtil.list();
            map.put(key, list);
        }
        list.add(value);
    }

    /**
        Merges <code>key</code> and the collection of <code>values</code>
        into <code>map</code>, by finding the collection of
        values already in <code>map</code> and adding <code>values</code>
        to it. <p/>

        @param map the map to merge into
        @param key the key
        @param values the collection of values
        @param factory the factory to use to create new collections if needed

        @aribaapi ariba
    */
    public static <K,V,C extends Collection<V>> void merge (
            Map<K,C> map,
            K key,
            Collection<? extends V> values,
            Factory<C> factory
    )
    {
        C collection = map.get(key);
        if (collection == null) {
            collection = factory.create();
            map.put(key, collection);
        }
        collection.addAll(values);

    }

    /**
        Convenience generic method that merges <code>key</code> and
        <code>value</code> into the supplied <code>map</code>. <p/>

        The semantics are, add <code>value</code> to the list of
        <code>values</code> associated with <code>key</code> in
        <code>map</code>. <p/>

        @param map the map to merge into
        @param key the key
        @param values the values

        @aribaapi ariba
    */
    public static <K,V> void merge (
            Map<K,List<V>> map,
            K key,
            Collection<? extends V> values
    )
    {
        merge(map, key, values, Factory.<V>listFactory());
    }

    /**
        Returns a string serialization of the Hashtable using the
        Serializer.

        @see Serializer

        @return string serialization of this Hashtable
        @aribaapi private
    */
    public static String toSerializedString (Map m)
    {
        StringWriter writer = new StringWriter();
        Serializer serializer = new Serializer(writer);

        try {
            serializer.writeObject(m);
            serializer.flush();
        }
        catch (IOException e) {
            Log.util.error(2756, e);
            return null;
        }

            // remember the result
        String result = writer.toString();

            // close the serializer and the stream
        try {
            serializer.close();
            writer.close();
        }
        catch (IOException e) {
        }

        return result;
    }

    /**
        Populates the hashtable with serialized data from the string.

        @param serialized String containing serialized Hashtable data
        @aribaapi private
    */
    public static void fromSerializedString (Map m, String serialized)
    {
        StringReader reader = new StringReader(serialized);

        try {
            new Deserializer(reader).readObject(m);
        }
        catch (IOException e) {
            Log.util.error(2757, e);
        }
        catch (DeserializationException e) {
            Log.util.error(2757, e);
        }
        finally {
            reader.close();
        }
    }

    private static final char Dot = '.';
    /**
     * Fetch the object (if any) in the designated Map, at the
     * coordinates specified by the path, using dot notation.
     *
     * @param map The map to search
     * @param path The dotted path to traverse
     * @return The Object at the location specified by path, if any. If no
     * such object exists, returns null.
     */
    public static Object getPath (Map map, String path)
    {
        Object value = map;
        String[] segments = StringUtil.delimitedStringToArray(path, Dot);
        for (int i=0; i<segments.length; i++) {
            if (value instanceof Map) {
                value = ((Map)value).get(segments[i]);
            }
            else {
                return null;
            }
        }
        return value;
    }

    private static final int MaxStringLen = 254;

    /**
        Converts a string into a string array for persistence purposes.

        @return string array serialization of this Hashtable
        @aribaapi private
    */
    public static String[] toStringArray (Map m)
    {
            //        fullString - the original full string
            // first convert to serialized string
        String fullString = toSerializedString(m);

            // allocate enough elements in the string array
        int numElements = fullString.length() / MaxStringLen;
        if (fullString.length() % MaxStringLen > 0) {
            ++numElements;
        }

            // allocate the array
        String[] newArray = new String[numElements];

            // break up the string into the string array
        for (int i = 0; i < numElements; ++i) {
            int endIndex = (i < numElements - 1) ?
                           MaxStringLen : fullString.length();
            newArray[i] = fullString.substring(0, endIndex);
            if (i < numElements - 1) {
                fullString = fullString.substring(MaxStringLen);
            }
        }

        return newArray;
    }


    /**
        Search a list for a map.
        Will only search this list, and not sub lists.

        @param l1 the list
        @param h1 the Map

        @return element location if the map is found, -1 otherwise
        @aribaapi documented
    */
    public static int indexOfMapInList (List l1, Map h1)
    {
        for (int i = 0; i < l1.size(); i++) {
            if ((l1.get(i) instanceof Map) &&
                (mapEquals((Map)l1.get(i), h1))) {
                return i;
            }
        }
        return -1;
    }

    /**
        A simple wrapper to convert an Iterator to an Enumeration.
        @param i the Iterator to convert to an Enumeration
        @return an enumeration wrapped around the iterator
        @aribaapi documented
    */
    public static Enumeration iteratorToEnumeration (Iterator i)
    {
        if (i == null) {
            return  null;
        }
        if (i instanceof WrappedIterator) {
            return ((WrappedIterator)i).backing;
        }
        return new WrappedEnumeration(i);
    }


    /**
        A simple wrapper to convert an Enumeration to an Iterator.
        The returned iterator may not support the remove() operation.

        @param e the Enumeration to convert to an Iterator
        @return an iterator wrapped around the enumeration

        @aribaapi documented
    */
    public static Iterator enumerationToIterator (Enumeration e)
    {
        if (e == null) {
            return null;
        }
        if (e instanceof WrappedEnumeration) {
            return ((WrappedEnumeration)e).backing;
        }
        return new WrappedIterator(e);
    }

    public static final Class ImmutableMapClass =
        Collections.unmodifiableMap(map()).getClass();

    /**
        Test a map to see if it is immutable.

        @param m The Map to be tested
        @return True if the Map m is immutable, False otherwise.
    */
    public static boolean isImmutable (Map m)
    {
        return m.getClass() == ImmutableMapClass;
    }

    /**
        Returns a version of the map that is not modifiable
        If m is null, null will be returned.
        @aribaapi ariba
    */
    public static Map immutableMap (Map m)
    {
            // Do this check to support general routines that protect
            // whatever map they are returning, such as return
            // Map.immutableMap(getFoo()); where the value being
            // passed may be null
        if (m == null) {
            return null;
        }
        return isImmutable(m) ? m : Collections.unmodifiableMap(m);
    }


    /**
        Make a map immutable at all levels.

        If the incoming map (aMap) contains maps and is fully mutable at all levels, it will be changed so that its contained maps
        are now immutable while the top level map is still mutable.  Callers cannot keep references to aMap and use it as fully
        mutable map.

        @param aMap - the Map to be made immutable.
        @return An immutable Map wrapping the original map, any subMaps of which have been replaced by immutable Maps
        wrapping the originals.
        @aribaapi ariba
    */
    public static Map makeImmutable (Map aMap)
    {
        if (aMap == null || isImmutable(aMap)) {
            return aMap;
        }
        Iterator keys = aMap.keySet().iterator();
        while (keys.hasNext()) {
            Object key = keys.next();
            Object element = aMap.get(key);
            if (element instanceof Map) {
                Map immutableElement = makeImmutable((Map)element);
                aMap.put(key, immutableElement);
            }
        }
        return immutableMap(aMap);
    }

    /**
     * Get a string value out of the map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the String value, or null if it isn't found for any reason
     */
    public static String getStringArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }

        Object value = args.get(key);
        if (! (value instanceof String)) {
            return null;
        }

        return (String)value;
    }

    /**
     * Get a List value out of the map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the List value, or null if it isn't found for any reason
     */
    public static List getVectorArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }

        Object value = args.get(key);
        if (! (value instanceof List)) {
            return null;
        }

        return (List)value;
    }

    /**
     * Get a Map value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Map value, or null if it isn't found for any reason
     */
    public static Map getHashtableArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }

        Object value = args.get(key);
        if (! (value instanceof Map)) {
            return null;
        }

        return (Map)value;
    }

    /**
     * Get a date value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Date value, or null if it isn't found for any reason
     */
    public static Date getDateArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }

        return DateFormatter.getDateValue(args.get(key));
    }

    /**
     * Get an int value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the int value, or 0 if it isn't found for any reason
     */
    public static int getIntArg (Map args, String key)
    {
        if (args == null || key == null) {
            return 0;
        }
        return IntegerFormatter.getIntValue(args.get(key));
    }

      /**
     * Get an int value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the int value, or null
     */
    public static Integer getIntArgOrNull (Map args, String key)
    {
        if (args == null || key == null || args.get(key) == null) {
            return null;
        }
        return IntegerFormatter.getIntValue(args.get(key));
    }
   
    /**
     * Get a double value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Double value, or 0 if it isn't found for any reason
     */
    public static Double getDoubleArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }
        return DoubleFormatter.getDoubleValue(args.get(key));
    }

    /**
     * Get a double value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Double value, or null if not present.
     */
    public static Double getDoubleArgOrNull (Map args, String key)
    {
        if (args == null || key == null || args.get(key) == null) {
            return null;
        }
        return DoubleFormatter.getDoubleValue(args.get(key));
    }

    /**
     * Get a long value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Long value, or 0 if it isn't found for any reason
     */
    public static Long getLongArg (Map args, String key)
    {
        if (args == null || key == null) {
            return null;
        }
        return LongFormatter.getLongValue(args.get(key));
    }

  /**
     * Get a long value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Long value, or null if it isn't found for any reason
     */
    public static Long getLongArgOrNull (Map args, String key)
    {
        if (args == null || key == null || args.get(key) == null) {
            return null;
        }
        return LongFormatter.getLongValue(args.get(key));
    }

    /**
     * Get a Big Decimal value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the BigDecimal value, or null if it isn't found for any reason
     */
    public static BigDecimal getBigDecimalArg (Map args, String key)
    {
        return BigDecimalFormatter.getBigDecimalValue(args.get(key));
    }

    /**
     * Get a Boolean value out of the exported map
     *
     * @param args the maps to get the key from
     * @param key the key of the value we're looking up
     * @return the Boolean value, or null if it isn't found for any reason
     */
    public static boolean getBooleanArg (Map args, String key)
    {
        if (args == null || key == null) {
            return false;
        }
        return BooleanFormatter.getBooleanValue(args.get(key));
    }

    public interface Transformer <V,W>
    {
        public W transform (V v);
    }

    public static <K,X,Y> Map<K,Y> transformValues (Map<K,X> m, Transformer<X,Y> t)
    {
        Map<K,Y> newMap = MapUtil.map(m.size());
        Iterator<K> keys = m.keySet().iterator();
        K key = null;
        while (keys.hasNext()) {
            key = keys.next();
            X x = m.get(key);
            newMap.put(key, t.transform(x));
        }
        return newMap;
    }


    public static Map diff (Map change, Map baseline)
    {
        Map delta = MapUtil.map();
        if (MapUtil.nullOrEmptyMap(baseline)) {
            delta = change;
        }
        else {
            Iterator keys = change.keySet().iterator();
            while (keys.hasNext()) {
                Object key = keys.next();
                if (baseline.containsKey(key)) {
                    Object baselineValue = baseline.get(key);
                    Object changeValue = change.get(key);
                    if (baselineValue != null) {
                        if (changeValue != null) {
                            if (!changeValue.equals(baselineValue)) {
                                if (   changeValue instanceof Map
                                        && baselineValue instanceof Map) {
                                    delta.put(key, diff((Map)changeValue,(Map)baselineValue));
                                    continue;
                                }
                                if (   changeValue instanceof List
                                        && baselineValue instanceof List) {
                                    delta.put(key, ListUtil.diff((List)changeValue,(List)baselineValue));
                                    continue;
                                }
                                if (!changeValue.equals(baselineValue)) {
                                    delta.put(key, changeValue);
                                }
                            }
                        }
                    }
                }
                else {
                    delta.put(key, change.get(key));
                }
            }
        }
        return delta;
    }
}

class WrappedEnumeration implements Enumeration
{
    public final Iterator backing;
    public WrappedEnumeration (Iterator i)
    {
        backing = i;
    }
    public boolean hasMoreElements ()
    {
        return backing.hasNext();
    }
    public Object nextElement ()
    {
        return backing.next();
    }
}

class WrappedIterator implements Iterator
{
    public final Enumeration backing;
    public WrappedIterator (Enumeration e)
    {
        backing = e;
    }
    public boolean hasNext ()
    {
        return backing.hasMoreElements();
    }
    public Object next ()
    {
        return backing.nextElement();
    }
    public void remove ()
    {
        throw new UnsupportedOperationException();
    }

}
TOP

Related Classes of ariba.util.core.WrappedEnumeration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.