pro.jk.ejoker.common.utils.relationship.RelationshipTreeRevertUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ejoker-common Show documentation
Show all versions of ejoker-common Show documentation
EJoker is a CQRS + EventSourcing framwork
package pro.jk.ejoker.common.utils.relationship;
import static pro.jk.ejoker.common.utils.relationship.RelationshipTreeUtil.checkIgnoreField;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.jk.ejoker.common.system.enhance.StringUtilx;
import pro.jk.ejoker.common.system.functional.IFunction;
import pro.jk.ejoker.common.system.functional.IVoidFunction;
import pro.jk.ejoker.common.system.functional.IVoidFunction1;
import pro.jk.ejoker.common.system.helper.Ensure;
import pro.jk.ejoker.common.utils.SerializableCheckerUtil;
import pro.jk.ejoker.common.utils.genericity.GenericDefinedType;
import pro.jk.ejoker.common.utils.genericity.GenericExpression;
import pro.jk.ejoker.common.utils.genericity.GenericExpressionFactory;
/**
* 对象关系二维化工具类
*
* @author kimffy
*
* @param
* @param
*/
public class RelationshipTreeRevertUtil extends AbstractRelationshipUtil{
private final static Logger logger = LoggerFactory.getLogger(RelationshipTreeRevertUtil.class);
private final IRelationshipTreeDisassemblers disassemblyEval;
public RelationshipTreeRevertUtil(IRelationshipTreeDisassemblers disassemblyEval,
SpecialTypeCodecStore> specialTypeCodecStore) {
super(specialTypeCodecStore);
this.disassemblyEval = disassemblyEval;
Ensure.notNull(disassemblyEval, "RelationshipTreeRevertUtil.disassemblyEval");
}
public RelationshipTreeRevertUtil(IRelationshipTreeDisassemblers disassemblyEval) {
this(disassemblyEval, null);
}
public T revert(ContainerKVP kvDataSet, Class clazz) {
Queue queue = new ConcurrentLinkedQueue<>();
// Queue queue = taskQueueBox.get();
T revertValue = (T )revertInternal(kvDataSet, GenericExpressionFactory.getGenericExpress(clazz), queue);
IVoidFunction task;
while(null != (task = queue.poll())) {
task.trigger();
};
return revertValue;
}
private Object revertInternal(ContainerKVP kvDataSet, GenericExpression expression, Queue subTaskQueue) {
Object instance = doCreateInstance(expression.getDeclarePrototype());
expression.forEachFieldExpressionsDeeply(
(fieldName, genericDefinedField) -> {
if(
checkIgnoreField(genericDefinedField.field)
|| !disassemblyEval.hasKey(kvDataSet, fieldName)) {
return;
}
disassemblyStructure(
genericDefinedField.genericDefinedType,
disassemblyEval.getValue(kvDataSet, fieldName),
result -> setField(genericDefinedField.field, instance, result.trigger()),
subTaskQueue
);
}
);
return instance;
}
private void disassemblyStructure(GenericDefinedType targetDefinedTypeMeta, Object serializedValue, IVoidFunction1> effector, Queue subTaskQueue) {
if(null == serializedValue) {
if(!targetDefinedTypeMeta.rawClazz.isPrimitive())
effector.trigger(() -> null);
return;
}
if(!targetDefinedTypeMeta.allHasMaterialized)
throw new RuntimeException("Unmatch genericity signature!!!");
final Class> definedClazz = targetDefinedTypeMeta.rawClazz;
Object revertedResult;
SpecialTypeCodec specialTypeCodec;
if(targetDefinedTypeMeta.isArray) {
if(!targetDefinedTypeMeta.hasGenericDeclare && definedClazz.isPrimitive()) {
revertedResult = revertPrivateTypeArray((ContainerVP )serializedValue, definedClazz);
} else {
// common
int size = disassemblyEval.getVPSize((ContainerVP )serializedValue);
Object[] newArray = (Object[] )Array.newInstance(definedClazz, size);
revertedResult = newArray;
for(int i=0; i disassemblyStructure(
targetDefinedTypeMeta.componentTypeMeta,
disassemblyEval.getValue((ContainerVP )serializedValue, idx),
result -> newArray[idx] = result.trigger(),
subTaskQueue
),
subTaskQueue
);
}
}
} else if(null != (specialTypeCodec = getDeserializeCodec(definedClazz))) {
revertedResult = specialTypeCodec.decode(serializedValue);
} else if(SerializableCheckerUtil.isDirectSerializableType(definedClazz)) {
/// 定义为可直接序列化类型
revertedResult = baseTypeConvert(definedClazz, serializedValue);
} else if (definedClazz.isEnum()) {
// 枚举还原
if(!String.class.equals(serializedValue)) {
revertedResult = revertIntoEnumType(definedClazz, (String )serializedValue);
} else {
logger.warn("Enum data should represent as a String!");
throw new RuntimeException(String.format("Revert %s#%s faild!!! serializedValue: %s", "", "", serializedValue.toString()));
}
} else if (SerializableCheckerUtil.hasSublevel(definedClazz)) {
if (Queue.class.isAssignableFrom(definedClazz)) {
if(!definedClazz.getSimpleName().endsWith("List"))
throw new RuntimeException("Unsupport revert type java.util.Queue!!!");
}
if (Collection.class.isAssignableFrom(definedClazz)) {
if(List.class.isAssignableFrom(definedClazz)) {
revertedResult = new LinkedList();
} else {
revertedResult = new HashSet();
}
int size = disassemblyEval.getVPSize((ContainerVP )serializedValue);
for(int i=0; i disassemblyStructure(
targetDefinedTypeMeta.deliveryTypeMetasTable[0],
disassemblyEval.getValue((ContainerVP )serializedValue, idx),
result -> ((Collection )revertedResult).add(result.trigger()),
subTaskQueue
),
subTaskQueue
);
}
} else {
/// map的情况
/// 按照RelationshipTreeUtil的转化 map的key一定是string类型的。
revertedResult = new HashMap();
GenericDefinedType valueTypeMeta = targetDefinedTypeMeta.deliveryTypeMetasTable[1];
Set keySet = disassemblyEval.getKeySet((ContainerKVP )serializedValue);
for(Object key:keySet) {
join(
() -> disassemblyStructure(
valueTypeMeta,
disassemblyEval.getValue((ContainerKVP )serializedValue, (String )key),
result -> ((Map )revertedResult).put((String )key, result.trigger()),
subTaskQueue
),
subTaskQueue
);
}
}
} else {
{
/// 不支持部分数据类型。
if (UnsupportTypes.isUnsupportType(definedClazz)) {
throw new RuntimeException(String.format("Unsupport type %s, unexcepted on %s#%s", definedClazz.getName(),
targetDefinedTypeMeta.getGenericDefination().genericPrototypeClazz.getName(),
"(# lose in foreach)"));
}
if (UnsupportTypes.isUnsupportType(serializedValue.getClass())) {
throw new RuntimeException(String.format("Unsupport type %s, unexcepted on %s#%s", definedClazz.getName(),
targetDefinedTypeMeta.getGenericDefination().genericPrototypeClazz.getName(),
"(# lose in foreach)"));
}
}
revertedResult = revertInternal((ContainerKVP )serializedValue, GenericExpressionFactory.getGenericExpress(definedClazz, targetDefinedTypeMeta.deliveryTypeMetasTable), subTaskQueue);
}
effector.trigger(() -> revertedResult);
}
private void join(IVoidFunction task, Queue subTaskQueue) {
if(!subTaskQueue.offer(task)) {
throw new RuntimeException("Task Queue has no more capacity!!!");
}
}
private void setField(Field field, Object instance, Object value) {
try {
field.set(instance, value);
} catch (IllegalArgumentException | IllegalAccessException e) {
logger.error("Cannot access field!!!", e);
throw new RuntimeException(e);
}
}
private Object baseTypeConvert(Class> definedClazz, Object target) {
Object res = null;
Class> targetClazz = target.getClass();
if(definedClazz.equals(targetClazz)) {
res = target;
} else if(Number.class.isAssignableFrom(targetClazz)) {
if(Long.class.equals(definedClazz) || long.class.equals(definedClazz)) {
res = ((Number )target).longValue();
} else if(Integer.class.equals(definedClazz) || int.class.equals(definedClazz)) {
res = ((Number )target).intValue();
} else if(Short.class.equals(definedClazz) || short.class.equals(definedClazz)) {
res = ((Number )target).shortValue();
} else if(Byte.class.equals(definedClazz) || byte.class.equals(definedClazz)) {
res = ((Number )target).byteValue();
} else if(Double.class.equals(definedClazz) || double.class.equals(definedClazz)) {
res = ((Number )target).doubleValue();
} else if(Float.class.equals(definedClazz) || float.class.equals(definedClazz)) {
res = ((Number )target).floatValue();
}
} else if(
(Character.class.equals(definedClazz) || char.class.equals(definedClazz)) &&
(Character.class.equals(targetClazz) || char.class.equals(targetClazz))
) {
res = target;
} else if(
(Boolean.class.equals(definedClazz) || boolean.class.equals(definedClazz)) &&
(Boolean.class.equals(targetClazz) || boolean.class.equals(targetClazz))
) {
res = target;
}
if(null == res)
throw new RuntimeException(String.format("Type convert faild!!! defined type: [%s], data type: [%s], data value: ", definedClazz.getName(), target.getClass().getName()) + target);
return res;
}
/**
* 还原枚举类型,通过枚举的表现字符值
*/
private TEnum revertIntoEnumType(Class enumType, String represent){
Object value = null;
if(enumType.isEnum()) {
Map> eInfoMap;
if(eMapItemPlaceHolder.equals(eInfoMap = eMap.getOrDefault(enumType, eMapItemPlaceHolder))) {
eInfoMap = new HashMap<>();
TEnum[] enumConstants = enumType.getEnumConstants();
for(TEnum obj:enumConstants) {
eInfoMap.put(obj.toString(), (Enum> )obj);
}
eMap.putIfAbsent((Class> )enumType, eInfoMap);
};
value = eInfoMap.get(represent);
} else {
throw new RuntimeException(String.format("[%s] is not a Enum type!!!", enumType.getName()));
}
if(null == value) {
throw new RuntimeException(String.format("[%s] has not such a value[%s]!!!", enumType.getName(), represent));
}
return (TEnum )value;
}
private Map>, Map>> eMap = new HashMap<>();
private final static Map> eMapItemPlaceHolder = new HashMap<>();
/**
* 尽量减少装箱操作。
* * 皆因java不支持基数类型的数组泛化
* @param valueSet
* @param componentType
* @param object
*/
private Object revertPrivateTypeArray(ContainerVP vpNode, Class> componentType) {
Object result;
if (int.class == componentType) {
// integer
int size = disassemblyEval.getVPSize(vpNode);
int[] rArray = (int[] )Array.newInstance(int.class, size);
for(int i=0; i T doCreateInstance(Class clazz) {
Object newInstance;
try {
newInstance = clazz.newInstance();
} catch (InstantiationException|IllegalAccessException e) {
String errInfo = StringUtilx.fmt("Connot create new instance!!! [type: {}]", clazz.getName());
logger.error(errInfo, e);
throw new RuntimeException(errInfo, e);
}
return (T )newInstance;
}
}