public static Map<String, Set<String>> parseAttributeToAttributeMapping(final Map<String, ?> mapping) {
        val mappedAttributesBuilder = new LinkedCaseInsensitiveMap<Set<String>>();
        for (val mappingEntry : mapping.entrySet()) {
            val sourceAttrName = mappingEntry.getKey();
            val mappedAttribute = mappingEntry.getValue();
            switch (mappedAttribute) {
                case null -> mappedAttributesBuilder.put(sourceAttrName, null);
                case final String value -> {
                    val mappedSet = new HashSet<String>();
                    mappedSet.add(mappedAttribute.toString());
                    mappedAttributesBuilder.put(sourceAttrName, mappedSet);
                }
                case final Collection sourceSet -> {
                    val mappedSet = new LinkedHashSet<String>();
                    for (val sourceObj : sourceSet) {
                        if (sourceObj != null) {
                            mappedSet.add(sourceObj.toString());
                        } else {
                            mappedSet.add(null);
                        }
                    }
                    mappedAttributesBuilder.put(sourceAttrName, mappedSet);
                }
                default -> throw new IllegalArgumentException("Invalid mapped type. key=" + sourceAttrName + ", value type=" + mappedAttribute.getClass().getName());
            }
        }

        return new HashMap<>(mappedAttributesBuilder);
    }
Translate from a more flexible Attribute to Attribute mapping format to a Map
from String to Set of Strings.
<p>
The point of the map is to map from attribute names in the underlying data store
(e.g., JDBC column names, LDAP attribute names) to uPortal attribute names.
Any given underlying data store attribute might map to zero uPortal
attributes (not appear in the map at all), map to exactly one uPortal attribute
(appear in the Map as a mapping from a String to a String or as a mapping
from a String to a Set containing just one String), or map to several uPortal
attribute names (appear in the Map as a mapping from a String to a Set
of Strings).
<p>
This method takes as its argument a {@link Map} that must have keys of
type {@link String} and values of type {@link String} or {@link Set} of
{@link String}s.  The argument must not be null and must have no null
keys.  It must contain no keys other than Strings and no values other
than Strings or Sets of Strings.  This method will convert any non-string
values to a String using the object's toString() method.
<p>
This method returns a Map equivalent to its argument except wherever there
was a String value in the Map there will instead be an immutable Set containing
the String value.  That is, the return value is normalized to be a Map from
String to Set (of String).

@param mapping {@link Map} from String names of attributes in the underlying store
               to attribute names or Sets of such names.
@return a Map from String to Set of Strings
core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/attribute/BasePersonAttributeDao.java