001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.oauth2.sdk.util;
019
020
021import java.util.*;
022
023
024/**
025 * Multi-valued map utilities.
026 */
027public final class MultivaluedMapUtils {
028        
029        
030        /**
031         * Converts the specified multi-valued map to a single-valued map by
032         * taking the first value in the list.
033         *
034         * @param map The multi-valued map, {@code null} if not specified.
035         *
036         * @return The single-valued map, {@code null} if no map was specified.
037         */
038        public static <K,V> Map<K,V> toSingleValuedMap(final Map<K,List<V>> map) {
039                
040                if (map == null)
041                        return null;
042                
043                Map<K,V> out = new HashMap<>();
044                
045                for (Map.Entry<K,List<V>> en: map.entrySet()) {
046                        
047                        if (en.getValue() == null || en.getValue().isEmpty()) {
048                                out.put(en.getKey(), null);
049                        } else {
050                                out.put(en.getKey(), en.getValue().get(0));
051                        }
052                }
053                
054                return out;
055        }
056        
057        
058        /**
059         * Gets the first value for the specified key.
060         *
061         * @param map The multi-valued map. Must not be {@code null}.
062         * @param key The key. Must not be {@code null}.
063         *
064         * @return The first value, {@code null} if not set.
065         */
066        public static <K,V> V getFirstValue(final Map<K,List<V>> map, final K key) {
067                
068                List<V> valueList = map.get(key);
069                
070                if (valueList == null || valueList.isEmpty()) {
071                        return null;
072                }
073                
074                return valueList.get(0);
075        }
076        
077        
078        /**
079         * Removes the entry for the specified key and returns its first value.
080         *
081         * @param map The multi-valued map. Must not be {@code null}.
082         * @param key The key. Must not be {@code null}.
083         *
084         * @return The first value, {@code null} if not set.
085         */
086        public static <K,V> V removeAndReturnFirstValue(final Map<K,List<V>> map, final String key) {
087                
088                List<V> valueList = map.remove(key);
089                
090                if (valueList == null || valueList.isEmpty()) {
091                        return null;
092                }
093                
094                return valueList.get(0);
095        }
096        
097        
098        /**
099         * Returns the keys with more than one distinct value. Keys that map to
100         * two or more identical values are treated as single-valued.
101         *
102         * @param map      The multi-valued map, {@code null} if not specified.
103         * @param excepted The excepted keys, {@code null} or empty if none.
104         *
105         * @return The keys with more than one distinct value, empty set if
106         *         none.
107         */
108        public static <K,V> Set<K> getKeysWithMoreThanOneValue(final Map<K,List<V>> map, final Set<K> excepted) {
109                
110                if (MapUtils.isEmpty(map)) {
111                        return Collections.emptySet();
112                }
113                
114                Set<K> found = new HashSet<>();
115                for (Map.Entry<K,List<V>> en: map.entrySet()) {
116                        
117                        if (CollectionUtils.contains(excepted, en.getKey())) {
118                                continue;
119                        }
120                        
121                        Set<V> entryValues = new HashSet<>(en.getValue());
122                        
123                        if (CollectionUtils.isNotEmpty(entryValues) && entryValues.size() > 1) {
124                                found.add(en.getKey());
125                        }
126                }
127                return found;
128        }
129        
130        
131        /**
132         * Prevents public instantiation.
133         */
134        private MultivaluedMapUtils() {}
135}