/*
* Copyright 2005 The Apache Software Foundation.
*
* 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 net.sf.beanlib.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Enum Utilities.
*
* @author Joe D. Velopar
*/
public class EnumUtils {
/**
* Contains a lazily initialized internal map used for implementing fromExternal().
*
* @author Joe D. Velopar
*/
private static class LazyExternal {
private static final ConcurrentMap<Class<?>, Map<?, ?>> enumExternalDirectory = new ConcurrentHashMap<Class<?>, Map<?, ?>>();
}
/**
* Contains a lazily initialized internal map used for implementing fromString().
*
* @author Joe D. Velopar
*/
private static class LazyToString {
private static final ConcurrentMap<Class<?>, Map<?, ?>> enumToStringDirectory = new ConcurrentHashMap<Class<?>, Map<?, ?>>();
}
/**
* Contains a lazily initialized internal map used for implementing fromOrdinal().
*
* @author Joe D. Velopar
*/
private static class LazyOrdinal {
private static final ConcurrentMap<Class<?>, Map<?, ?>> enumOrdinalDirectory = new ConcurrentHashMap<Class<?>, Map<?, ?>>();
}
/**
* Returns the enum constant of the specified Enum and External type with the specified externalized object; or null
* if no such enum constant exists. Note this method may break unless E is immutable.
*/
public static <T extends Enum<T> & External<E>, E> T fromExternal(Class<T> enumType, E externalized) {
return enumConstantDirectory(enumType).get(externalized);
}
/**
* Returns the enum constant of the specified Enum with the specified toString() return value of the enum constant;
* or null if no such enum constant exists.
*/
public static <T extends Enum<T>> T fromString(Class<T> enumType, String s) {
return enumStringConstantDirectory(enumType).get(s);
}
/**
* Returns the enum constant of the specified Enum with the specified ordinal() return value of the enum constant;
* or null if no such enum constant exists.
*/
public static <T extends Enum<T>> T fromOrdinal(Class<T> enumType, int ordinal) {
return enumOrdinalConstantDirectory(enumType).get(ordinal);
}
/**
* Returns a map from the externalized object of type E to enum constant for the specified T, which has a type of
* both Enum and External. This private method is used internally to implement
*
* <pre>
* public static <T extends Enum<T> & External<E>> T fromExternal(Class<T>, E)
* </pre>
*
* efficiently. Note that the map returned by this method is created lazily on first use. Typically it won't ever
* get created.
*/
private static <T extends Enum<T> & External<E>, E> Map<E, T> enumConstantDirectory(Class<T> enumType) {
@SuppressWarnings("unchecked")
Map<E, T> constantMap = (Map<E, T>) LazyExternal.enumExternalDirectory.get(enumType);
if (constantMap == null) {
T[] constants = enumType.getEnumConstants(); // Does unnecessary clone
constantMap = new HashMap<E, T>(2 * constants.length);
for (T constant : constants)
constantMap.put(constant.externalize(), constant);
@SuppressWarnings("unchecked")
Map<E, T> prev = (Map<E, T>) LazyExternal.enumExternalDirectory.putIfAbsent(enumType, Collections.unmodifiableMap(constantMap));
if (prev != null)
constantMap = prev; // race condition
}
return constantMap;
}
/**
* Returns a map from the toString() return value to the enum constant for the specified T, which is an Enum. This
* private method is used internally to implement
*
* <pre>
* public static <T extends Enum<T>> T fromString(Class<T>, String)
* </pre>
*
* efficiently. Note that the map returned by this method is created lazily on first use. Typically it won't ever
* get created.
*/
private static <T extends Enum<T>> Map<String, T> enumStringConstantDirectory(Class<T> enumType) {
@SuppressWarnings("unchecked")
Map<String, T> constantMap = (Map<String, T>) LazyToString.enumToStringDirectory.get(enumType);
if (constantMap == null) {
T[] constants = enumType.getEnumConstants(); // Does unnecessary clone
constantMap = new HashMap<String, T>(2 * constants.length);
for (T constant : constants)
constantMap.put(constant.toString(), constant);
@SuppressWarnings("unchecked")
Map<String, T> prev = (Map<String, T>) LazyToString.enumToStringDirectory.putIfAbsent(enumType, Collections.unmodifiableMap(constantMap));
if (prev != null)
constantMap = prev; // race condition
}
return constantMap;
}
/**
* Returns a map from the ordinal() return value to the enum constant for the specified T, which is an Enum. This
* private method is used internally to implement
*
* <pre>
* public static <T extends Enum<T>> T fromOrdinal(Class<T>, int)
* </pre>
*
* efficiently. Note that the map returned by this method is created lazily on first use. Typically it won't ever
* get created.
*/
private static <T extends Enum<T>> Map<Integer, T> enumOrdinalConstantDirectory(Class<T> enumType) {
@SuppressWarnings("unchecked")
Map<Integer, T> constantMap = (Map<Integer, T>) LazyOrdinal.enumOrdinalDirectory.get(enumType);
if (constantMap == null) {
T[] constants = enumType.getEnumConstants(); // Does unnecessary clone
constantMap = new HashMap<Integer, T>(2 * constants.length);
for (T constant : constants)
constantMap.put(constant.ordinal(), constant);
@SuppressWarnings("unchecked")
Map<Integer, T> prev = (Map<Integer, T>) LazyOrdinal.enumOrdinalDirectory.putIfAbsent(enumType, Collections.unmodifiableMap(constantMap));
if (prev != null)
constantMap = prev; // race condition
}
return constantMap;
}
private EnumUtils() {}
}