@@ -0,0 +1,3164 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.%0A// Licensed under the MIT License.%0A%0Apackage com.azure.common.util;%0A%0Aimport com.fasterxml.jackson.annotation.JsonValue;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.Collection;%0Aimport java.util.HashSet;%0Aimport java.util.concurrent.ConcurrentHashMap;%0Aimport java.util.concurrent.ConcurrentMap;%0A%0A/**%0A * Base implementation for expandable, single string enums.%0A * @param %3CT%3E a specific expandable enum type%0A */%0Apublic abstract class ExpandableStringEnum%3CT extends ExpandableStringEnum%3CT%3E%3E %7B%0A    private static ConcurrentMap%3CString, ? extends ExpandableStringEnum%3C?%3E%3E valuesByName = null;%0A%0A    private String name;%0A    private Class%3CT%3E clazz;%0A%0A    private static String uniqueKey(Class%3C?%3E clazz, String name) %7B%0A        if (clazz != null) %7B%0A            return (clazz.getName() + %22#%22 + name).toLowerCase();%0A        %7D else %7B%0A            throw new IllegalArgumentException();%0A        %7D%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    protected T withNameValue(String name, T value, Class%3CT%3E clazz) %7B%0A        if (valuesByName == null) %7B%0A            valuesByName = new ConcurrentHashMap%3CString, T%3E();%0A        %7D%0A        this.name = name;%0A        this.clazz = clazz;%0A        ((ConcurrentMap%3CString, T%3E) valuesByName).put(uniqueKey(clazz, name), value);%0A        return (T) this;%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    protected static %3CT extends ExpandableStringEnum%3CT%3E%3E T fromString(String name, Class%3CT%3E clazz) %7B%0A        if (name == null) %7B%0A            return null;%0A        %7D else if (valuesByName != null) %7B%0A            T value = (T) valuesByName.get(uniqueKey(clazz, name));%0A            if (value != null) %7B%0A                return value;%0A            %7D%0A        %7D%0A%0A        try %7B%0A            T value = clazz.newInstance();%0A            return value.withNameValue(name, value, clazz);%0A        %7D catch (InstantiationException e) %7B%0A            return null;%0A        %7D catch (IllegalAccessException e) %7B%0A            return null;%0A        %7D%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    protected static %3CT extends ExpandableStringEnum%3CT%3E%3E Collection%3CT%3E values(Class%3CT%3E clazz) %7B%0A        // Make a copy of all values%0A        Collection%3C? extends ExpandableStringEnum%3C?%3E%3E values = new ArrayList%3C%3E(valuesByName.values());%0A%0A        Collection%3CT%3E list = new HashSet%3CT%3E();%0A        for (ExpandableStringEnum%3C?%3E value : values) %7B%0A            if (value.getClass().isAssignableFrom(clazz)) %7B%0A                list.add((T) value);%0A            %7D%0A        %7D%0A%0A        return list;%0A    %7D%0A%0A    @Override%0A    @JsonValue%0A    public String toString() %7B%0A        return this.name;%0A    %7D%0A%0A    @Override%0A    public int hashCode() %7B%0A        return uniqueKey(this.clazz, this.name).hashCode();%0A    %7D%0A%0A    @SuppressWarnings(%22unchecked%22)%0A    @Override%0A    public boolean equals(Object obj) %7B%0A        if (!clazz.isAssignableFrom(obj.getClass())) %7B%0A            return false;%0A        %7D else if (obj == this) %7B%0A            return true;%0A        %7D else if (this.name == null) %7B%0A            return ((ExpandableStringEnum%3CT%3E) obj).name == null;%0A        %7D else %7B%0A            return this.name.equals(((ExpandableStringEnum%3CT%3E) obj).name);%0A        %7D%0A    %7D%0A%7D%0A

Add expandable string enum base type (#3414)