11d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistpackage com.android.server.wifi.hotspot2.omadm;
21d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
31d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.ArrayList;
41d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.Collection;
51d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.Iterator;
61d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.LinkedHashMap;
71d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.List;
81d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistimport java.util.Map;
91d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
101d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvistpublic class MultiValueMap<T> {
111d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    private final Map<String, ArrayList<T>> mMap = new LinkedHashMap<>();
121d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
131d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public void put(String key, T value) {
141d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        key = key.toLowerCase();
151d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        ArrayList<T> values = mMap.get(key);
161d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values == null) {
171d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            values = new ArrayList<>();
181d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            mMap.put(key, values);
191d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
201d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        values.add(value);
211d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
221d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
231d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public T get(String key) {
241d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        key = key.toLowerCase();
251d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        List<T> values = mMap.get(key);
261d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values == null) {
271d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            return null;
281d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
291d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        else if (values.size() == 1) {
301d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            return values.get(0);
311d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
321d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        else {
331d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            throw new IllegalArgumentException("Cannot do get on multi-value");
341d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
351d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
361d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
371d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public T replace(String key, T oldValue, T newValue) {
381d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        key = key.toLowerCase();
391d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        List<T> values = mMap.get(key);
401d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values == null) {
411d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            return null;
421d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
431d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
441d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        for (int n = 0; n < values.size(); n++) {
451d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            T value = values.get(n);
461d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            if (value == oldValue) {
471d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                values.set(n, newValue);
481d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                return value;
491d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
501d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
511d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return null;
521d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
531d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
541d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public T remove(String key, T value) {
551d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        key = key.toLowerCase();
561d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        List<T> values = mMap.get(key);
571d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values == null) {
581d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            return null;
591d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
601d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
611d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        T result = null;
621d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        Iterator<T> valueIterator = values.iterator();
631d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        while (valueIterator.hasNext()) {
641d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            if (valueIterator.next() == value) {
651d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                valueIterator.remove();
661d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                result = value;
671d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                break;
681d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
691d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
701d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values.isEmpty()) {
711d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            mMap.remove(key);
721d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
731d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return result;
741d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
751d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
761d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public T remove(T value) {
771d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        T result = null;
781d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        Iterator<Map.Entry<String, ArrayList<T>>> iterator = mMap.entrySet().iterator();
791d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        while (iterator.hasNext()) {
801d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            ArrayList<T> values = iterator.next().getValue();
811d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            Iterator<T> valueIterator = values.iterator();
821d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            while (valueIterator.hasNext()) {
831d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                if (valueIterator.next() == value) {
841d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    valueIterator.remove();
851d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    result = value;
861d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    break;
871d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                }
881d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
891d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            if (result != null) {
901d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                if (values.isEmpty()) {
911d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                    iterator.remove();
921d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                }
931d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                break;
941d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
951d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
961d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return result;
971d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
981d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
991d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public Collection<T> values() {
1001d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        List<T> allValues = new ArrayList<>(mMap.size());
1011d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        for (List<T> values : mMap.values()) {
1021d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            for (T value : values) {
1031d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                allValues.add(value);
1041d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            }
1051d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
1061d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return allValues;
1071d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
1081d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist
1091d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public T getSingletonValue() {
1101d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (mMap.size() != 1) {
1111d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            throw new IllegalArgumentException("Map is not a single entry map");
1121d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
1131d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        List<T> values = mMap.values().iterator().next();
1141d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        if (values.size() != 1) {
1151d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist            throw new IllegalArgumentException("Map is not a single entry map");
1161d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        }
1171d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return values.iterator().next();
1181d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    }
1191d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist}
120