ninja.leaping.configurate.util.EnumLookup Maven / Gradle / Ivy
/**
* Configurate
* Copyright (C) zml and Configurate contributors
*
* 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 ninja.leaping.configurate.util;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Utility class to cache more flexible enum lookup. While normally case and punctuation have to match exactly, this
* method performs lookup that:
*
* - is case-insensitive
* - ignores underscores
* - Caches mappings
*
*
* If the enum has two fields that are equal except for case and underscores, an exact match will return the
* appropriate value, and any fuzzy matches will map to the first value in the enum that is applicable.
*/
public class EnumLookup {
private static final LoadingCache>, Map>> enumFieldCache = CacheBuilder
.newBuilder()
.weakKeys()
.maximumSize(512)
.build(new CacheLoader>, Map>>() {
@Override
public Map> load(Class extends Enum>> key) throws Exception {
Map> ret = new HashMap<>();
for (Enum> field : key.getEnumConstants()) {
ret.put(field.name(), field);
ret.putIfAbsent(processKey(field.name()), field);
}
return ImmutableMap.copyOf(ret);
}
});
private EnumLookup() {
// wheeeeeeee
}
private static String processKey(String key) {
checkNotNull(key, "key");
return "🌸" + key.toLowerCase().replace("_", ""); // stick a flower at the front so processed keys are
// different from literal keys
}
@SuppressWarnings("unchecked")
public static > Optional lookupEnum(Class clazz, String key) {
checkNotNull(clazz, "clazz");
try {
Map> vals = enumFieldCache.get(clazz);
Enum> possibleRet = vals.get(key);
if (possibleRet != null) {
return Optional.of((T) possibleRet);
}
return Optional.ofNullable((T) vals.get(processKey(key)));
} catch (ExecutionException e) {
return Optional.empty();
}
}
}