/**
* Copyright (c) Lambda Innovation, 2013-2015
* 本作品版权由Lambda Innovation所有。
* http://www.li-dev.cn/
*
* This project is open-source, and it is distributed under
* the terms of GNU General Public License. You can modify
* and distribute freely as long as you follow the license.
* 本项目是一个开源项目,且遵循GNU通用公共授权协议。
* 在遵照该协议的情况下,您可以自由传播和修改。
* http://www.gnu.org/licenses/gpl.html
*/
package cn.annoreg.core;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
public class RegistryHelper {
private final RegistryType parent;
public RegistryHelper(RegistryType parent) {
this.parent = parent;
}
/*
* ID map
*/
private Map<RegModInformation, Integer> idMap = new HashMap();
private int firstID = 0;
public int getNextIDForMod() {
RegModInformation mod = parent.getCurrentMod();
if (idMap.containsKey(mod)) {
int ret = idMap.get(mod);
idMap.put(mod, ret + 1);
return ret;
} else {
int ret = firstID;
idMap.put(mod, ret + 1);
return ret;
}
}
public void setFirstID(int id) {
if (!idMap.isEmpty()) {
throw new RuntimeException("Try to set initial id after registration.");
}
firstID = id;
}
/*
* Mod field
* Used in RegistryTypes that needs extra information (a field with a certain annotation) from the Mod instance.
*/
private Class<? extends Annotation> modFieldAnno;
private Map<RegModInformation, Object> modFieldCache = new HashMap();
public void setModFieldAnnotation(Class<? extends Annotation> anno) {
modFieldAnno = anno;
modFieldCache.clear();
}
public Object getModField() {
RegModInformation modInfo = parent.getCurrentMod();
if (modFieldCache.containsKey(modInfo)) {
return modFieldCache.get(modInfo);
}
Object mod = modInfo.getModInstance();
Object ret = getFieldFromObject(mod, modFieldAnno);
modFieldCache.put(modInfo, ret);
return ret;
}
/**
* Helper function used to get the value of a field (with anno) in the given class.
* @param clazz
* @param anno
* @return
*/
public final Object getFieldFromClass(Class<?> clazz, Class<? extends Annotation> anno) {
for (Field field : clazz.getFields()) {
if (field.isAnnotationPresent(anno)) {
if (!Modifier.isStatic(field.getModifiers())) {
throw new RuntimeException("The field must be static.");
}
try {
Object ret = field.get(null);//TODO should not use null
if (ret == null) {
ret = field.getType().newInstance();
field.set(null, ret);
}
return ret;
} catch (Exception e) {
throw new RuntimeException("Can not get field from mod class: get failed.", e);
}
}
}
throw new RuntimeException("Can not get field from mod " + clazz + ": field not found.");
}
public final Object getFieldFromObject(Object obj, Class<? extends Annotation> anno) {
for (Field field : obj.getClass().getFields()) {
if (field.isAnnotationPresent(anno)) {
try {
field.setAccessible(true);
if (Modifier.isStatic(field.getModifiers())) {
Object ret = field.get(null);
if (ret == null) {
ret = field.getType().newInstance();
field.set(null, ret);
}
return ret;
} else {
Object ret = field.get(obj);
if (ret == null) {
ret = field.getType().newInstance();
field.set(obj, ret);
}
return ret;
}
} catch (Exception e) {
throw new RuntimeException("Can not get field from mod class: get failed.", e);
}
}
}
throw new RuntimeException("Can not get field from mod class: field not found.");
}
}