package de.take_weiland.mods.commons.internal.exclude;
import com.google.common.collect.*;
import de.take_weiland.mods.commons.asm.info.ClassInfo;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.ForgeSubscribe;
import net.minecraftforge.event.world.WorldEvent;
import java.util.Map;
import java.util.Set;
/**
* @author diesieben07
*/
public final class ClassInfoUtil {
public static void preInit() {
MinecraftForge.EVENT_BUS.register(new ClassInfoUtil());
}
@ForgeSubscribe
public void onWorldLoad(WorldEvent.Load event) {
if (event.world.isRemote) {
return;
}
// null out the superCache once any world is loaded
// ClassInfo is only really used with ASM code (class transformers)
// they should be done at this point and holding onto all this information
// is nothing but a memory hog
superCache = null;
MinecraftForge.EVENT_BUS.unregister(this);
}
private static volatile Map<String, ImmutableSet<String>> superCache = Maps.newHashMap();
public static Set<String> getSupers(ClassInfo classInfo) {
// grab a local var in case of concurrency
Map<String, ImmutableSet<String>> superCacheLocal = superCache;
if (superCacheLocal != null) {
ImmutableSet<String> supers;
synchronized (ClassInfoUtil.class) {
supers = superCacheLocal.get(classInfo.internalName());
}
if (supers == null) {
supers = buildSupers(classInfo);
synchronized (ClassInfoUtil.class) {
// in theory someone else might have done this already
// but oh well, the data is the same
superCacheLocal.put(classInfo.internalName(), supers);
}
}
return supers;
} else {
return buildSupers(classInfo);
}
}
private static ImmutableSet<String> buildSupers(ClassInfo classInfo) {
Set<String> set = Sets.newHashSet();
String superName = classInfo.superName();
if (superName != null) {
set.add(superName);
set.addAll(classInfo.superclass().getSupers());
}
for (String iface : classInfo.interfaces()) {
if (set.add(iface)) {
set.addAll(ClassInfo.of(iface).getSupers());
}
}
// use immutable set to reduce memory footprint and potentially increase performance
// cannot use builder because we need the boolean return from set.add
return ImmutableSet.copyOf(set);
}
private ClassInfoUtil() {
}
}