这些文件不是我创建的,不知道为啥会在我这……
This commit is contained in:
parent
f82e500572
commit
4cb965ce71
@ -0,0 +1,88 @@
|
||||
package club.joylink.rtss.iscs.proto.model;
|
||||
|
||||
import club.joylink.iscs.model.data.DataModelMapProto;
|
||||
import club.joylink.iscs.model.data.DataModelProto;
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ModelMemory {
|
||||
|
||||
/**
|
||||
* 获取模型数据的引用
|
||||
*/
|
||||
DataModelProto.ModelRef.Builder refFrom(GeneratedMessageV3 model) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取引用引用的模型实例数据
|
||||
*/
|
||||
<T extends GeneratedMessageV3> T modelFrom(DataModelProto.ModelRef.Builder ref) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取引用引用的模型实例数据
|
||||
*/
|
||||
<T extends GeneratedMessageV3> T modelFrom(DataModelProto.ModelRef ref) throws Exception;
|
||||
|
||||
/**
|
||||
* 获取所有模型数据的副本
|
||||
*/
|
||||
DataModelMapProto.DataModelMap allDataModels();
|
||||
|
||||
/**
|
||||
* 从已有数据恢复模型数据
|
||||
*/
|
||||
void recoverFrom(DataModelMapProto.DataModelMap modelsData);
|
||||
|
||||
/**
|
||||
* 从已有数据恢复模型数据
|
||||
*/
|
||||
void recoverFrom(byte[] modelsData) throws InvalidProtocolBufferException;
|
||||
|
||||
public static ModelMemory create(byte[] modelsData) throws InvalidProtocolBufferException {
|
||||
ModelMemoryImpl impl = new ModelMemoryImpl();
|
||||
impl.recoverFrom(modelsData);
|
||||
return impl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型的身份信息
|
||||
*/
|
||||
public static DataModelProto.DataModel identityFrom(GeneratedMessageV3 model) throws Exception {
|
||||
//getIdentity
|
||||
Method getIdentity = getDeclaredMethod(model.getClass(), "getIdentity");
|
||||
if (null != getIdentity) {
|
||||
return (DataModelProto.DataModel) getIdentity.invoke(model);
|
||||
}
|
||||
//遍历
|
||||
final Method[] mds = model.getClass().getMethods();
|
||||
int count = 0;
|
||||
for (Method md : mds) {
|
||||
if (DataModelProto.DataModel.class.equals(md.getReturnType())) {
|
||||
getIdentity = md;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 1) {
|
||||
throw new Exception(String.format("%s 中 表示身份信息DataModelProto.DataModel有多个,可以将其中一个命名为'identity'表示身份信息", model.getClass().getSimpleName()));
|
||||
}
|
||||
if (count < 1) {
|
||||
throw new Exception(String.format("%s 中 没有表示身份信息DataModelProto.DataModel,可以添加一个命名为'identity'", model.getClass().getSimpleName()));
|
||||
}
|
||||
return (DataModelProto.DataModel) getIdentity.invoke(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型类型获取该类模型的集合,可以通过遍历该集合来遍历该类的所有模型数据
|
||||
*/
|
||||
public <M extends GeneratedMessageV3> Map<String, M> getModelMap(Class<M> modelClass) throws Exception;
|
||||
|
||||
static Method getDeclaredMethod(Class cls, String name, Class<?>... parameterTypes) {
|
||||
try {
|
||||
return cls.getDeclaredMethod(name, parameterTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
package club.joylink.rtss.iscs.proto.model;
|
||||
|
||||
import club.joylink.iscs.model.data.DataModelMapProto;
|
||||
import club.joylink.iscs.model.data.DataModelProto;
|
||||
import com.google.protobuf.GeneratedMessageV3;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 模型数据存储实现
|
||||
*/
|
||||
@Slf4j
|
||||
public class ModelMemoryImpl implements ModelMemory {
|
||||
|
||||
/**
|
||||
* 模型数据存储空间
|
||||
*/
|
||||
private DataModelMapProto.DataModelMap.Builder dmmBuilder = DataModelMapProto.DataModelMap.newBuilder();
|
||||
/**
|
||||
* 模型分类查找实现
|
||||
*/
|
||||
private final Map<DataModelProto.ModelType, Method> refMethodMap = new HashMap<>();
|
||||
/**
|
||||
* 快速存储模型数据实现
|
||||
*/
|
||||
private final Map<Class<? extends GeneratedMessageV3>, Method> putMethodMap = new HashMap<>();
|
||||
/**
|
||||
* 快速通过模型类获取模型的集合
|
||||
*/
|
||||
private final Map<Class<? extends GeneratedMessageV3>, Method> modelMap = new HashMap<>();
|
||||
|
||||
public ModelMemoryImpl() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模型数据的引用
|
||||
*/
|
||||
public synchronized DataModelProto.ModelRef.Builder refFrom(GeneratedMessageV3 model) throws Exception {
|
||||
final DataModelProto.DataModel identify = ModelMemory.identityFrom(model);
|
||||
this.putModelData(identify, model);
|
||||
return DataModelProto.ModelRef.newBuilder().setType(identify.getType()).setId(identify.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取引用引用的模型实例数据
|
||||
*/
|
||||
public synchronized <T extends GeneratedMessageV3> T modelFrom(DataModelProto.ModelRef.Builder ref) throws Exception {
|
||||
return (T) findFromMap(ref.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取引用引用的模型实例数据
|
||||
*/
|
||||
public synchronized <T extends GeneratedMessageV3> T modelFrom(DataModelProto.ModelRef ref) throws Exception {
|
||||
return (T) findFromMap(ref);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有模型数据的副本
|
||||
*/
|
||||
public synchronized DataModelMapProto.DataModelMap allDataModels() {
|
||||
return this.dmmBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从已有数据恢复模型数据
|
||||
*/
|
||||
public synchronized void recoverFrom(DataModelMapProto.DataModelMap modelsData) {
|
||||
this.dmmBuilder = DataModelMapProto.DataModelMap.newBuilder(modelsData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从已有数据恢复模型数据
|
||||
*/
|
||||
public synchronized void recoverFrom(byte[] modelsData) throws InvalidProtocolBufferException {
|
||||
this.dmmBuilder = DataModelMapProto.DataModelMap.newBuilder(DataModelMapProto.DataModelMap.parseFrom(modelsData));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模型类型获取该类模型的集合,可以通过遍历该集合来遍历该类的所有模型数据
|
||||
*/
|
||||
public synchronized <M extends GeneratedMessageV3> Map<String, M> getModelMap(Class<M> modelClass) throws Exception {
|
||||
final Map<String, M> rt = doFindByModelClass(modelClass);
|
||||
if (null != rt) {
|
||||
return rt;
|
||||
}
|
||||
//遍历所有集合查找
|
||||
Method[] mds = dmmBuilder.getClass().getMethods();
|
||||
for (Method md : mds) {
|
||||
final String mdName = md.getName();
|
||||
if (mdName.startsWith("get") && mdName.endsWith("Map")) {
|
||||
final Map map = (Map) md.invoke(dmmBuilder);
|
||||
for (Object v : map.values()) {
|
||||
if (v.getClass().equals(modelClass)) {
|
||||
this.modelMap.put(modelClass, md);
|
||||
show("==>>遍历获取模型的集合:modelClass = " + modelClass.getSimpleName());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 存储实例
|
||||
*/
|
||||
private void putModelData(final DataModelProto.DataModel identify, final GeneratedMessageV3 model) throws Exception {
|
||||
final Method putModelMethod = this.putMethodMap.get(model.getClass());
|
||||
if (null != putModelMethod) {
|
||||
putModelMethod.invoke(this.dmmBuilder, identify.getId(), model);
|
||||
show("==>>存储方法存在,直接存储:type = " + identify.getType() + " code = " + identify.getId());
|
||||
} else {
|
||||
final Method[] putMds = this.dmmBuilder.getClass().getMethods();
|
||||
for (Method putMd : putMds) {
|
||||
final String putMdName = putMd.getName();
|
||||
if (putMdName.startsWith("put")) {
|
||||
final Class<?>[] pts = putMd.getParameterTypes();
|
||||
if (null != pts && pts.length == 2) {
|
||||
if (pts[0].equals(String.class) && pts[1].equals(model.getClass())) {
|
||||
if (!this.putMethodMap.containsKey(model.getClass())) {
|
||||
this.putMethodMap.put(model.getClass(), putMd);
|
||||
}
|
||||
putMd.invoke(this.dmmBuilder, identify.getId(), model);
|
||||
show("==>>存储方法不存在,储遍历存储:type = " + identify.getType() + " code = " + identify.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private GeneratedMessageV3 findFromMap(DataModelProto.ModelRef ref) throws Exception {
|
||||
return this.doFindFromMap(ref);
|
||||
}
|
||||
|
||||
private Map doFindByModelClass(Class modelClass) throws Exception {
|
||||
Method md = this.modelMap.get(modelClass);
|
||||
if (null != md) {
|
||||
final Map map = (Map) md.invoke(dmmBuilder);
|
||||
show("==>>直接获取模型的集合:modelClass = " + modelClass.getSimpleName());
|
||||
return map;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历所有map来查找ref对应的model实例
|
||||
*/
|
||||
private GeneratedMessageV3 doFindFromMap(DataModelProto.ModelRef ref) throws Exception {
|
||||
//优先通过类型来查找
|
||||
GeneratedMessageV3 model = this.doFindByType(ref);
|
||||
if (null != model) {
|
||||
show("==>>优先通过类型找到:type = " + ref.getType() + " code = " + ref.getId());
|
||||
return model;
|
||||
}
|
||||
//遍历所有集合查找
|
||||
Method[] mds = dmmBuilder.getClass().getMethods();
|
||||
for (Method md : mds) {
|
||||
final String mdName = md.getName();
|
||||
if (mdName.startsWith("get") && mdName.endsWith("Map")) {
|
||||
Map map = (Map) md.invoke(dmmBuilder);
|
||||
model = (GeneratedMessageV3) map.get(ref.getId());
|
||||
if (null != model) {
|
||||
if (!DataModelProto.ModelType.Any.equals(ref.getType())) {
|
||||
if (!refMethodMap.containsKey(ref.getType())) {
|
||||
refMethodMap.put(ref.getType(), md);
|
||||
show("==>>保存类型查找信息:type = " + ref.getType() + " getMapMethod = " + mdName);
|
||||
}
|
||||
}
|
||||
show("==>>通过遍历所有集合找到:type = " + ref.getType() + " code = " + ref.getId());
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过类型来查找模型实例
|
||||
*/
|
||||
private GeneratedMessageV3 doFindByType(DataModelProto.ModelRef ref) throws Exception {
|
||||
//getXXXMap()
|
||||
final Method getMapMethod = refMethodMap.get(ref.getType());
|
||||
if (null != getMapMethod) {
|
||||
final Map map = (Map) getMapMethod.invoke(dmmBuilder);
|
||||
return (GeneratedMessageV3) map.get(ref.getId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void show(String msg) {
|
||||
log.debug(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package club.joylink.rtss.iscs.services;
|
||||
|
||||
import club.joylink.rtss.iscs.dao.IscsModelDataDAO;
|
||||
import club.joylink.rtss.iscs.entity.IscsModelData;
|
||||
import club.joylink.rtss.iscs.entity.IscsModelDataExample;
|
||||
import club.joylink.rtss.iscs.proto.model.ModelMemory;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* iscs模型使用业务实现<br>
|
||||
* iscs的所有页面的模型数据
|
||||
*/
|
||||
@Service
|
||||
public class IscsModelMemoryService {
|
||||
@Autowired
|
||||
private IscsModelDataDAO modelDataDao;
|
||||
/**
|
||||
* key : iscs的类型<br>
|
||||
* value : iscs的所有页面的模型数据<br>
|
||||
*/
|
||||
private final Map<String, Map<ModelMemoryIndex, ModelMemory>> modelMemoryMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* iscs启动时加载模型数据
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public void loadModelData() throws Exception {
|
||||
final List<ModelMemoryIndex> mmiList = this.findAllModelMemoryIndex(ISCS_DEFAULT_TYPE);
|
||||
for (ModelMemoryIndex mmi : mmiList) {
|
||||
final Map<ModelMemoryIndex, ModelMemory> map = getIscsModelMap(mmi.type);
|
||||
map.put(mmi, this.loadModelMemory(mmi));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
private synchronized Map<ModelMemoryIndex, ModelMemory> getIscsModelMap(String iscsType) {
|
||||
Map<ModelMemoryIndex, ModelMemory> map = modelMemoryMap.get(iscsType);
|
||||
if (null == map) {
|
||||
map = new ConcurrentHashMap<>();
|
||||
modelMemoryMap.put(iscsType, map);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private List<ModelMemoryIndex> findAllModelMemoryIndex(String iscsType) {
|
||||
final List<ModelMemoryIndex> rt = new ArrayList<>();
|
||||
//
|
||||
final IscsModelDataExample example = new IscsModelDataExample();
|
||||
final List<IscsModelData> list = modelDataDao.selectByExample(example);
|
||||
if (null != list) {
|
||||
list.forEach(md -> {
|
||||
rt.add(new ModelMemoryIndex(md.getSystem(), md.getView(), md.getPlace()));
|
||||
});
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
private ModelMemory loadModelMemory(ModelMemoryIndex mmi) throws Exception {
|
||||
IscsModelDataExample example = new IscsModelDataExample();
|
||||
example.createCriteria().andSystemEqualTo(mmi.system).andViewEqualTo(mmi.view).andPlaceEqualTo(mmi.place);
|
||||
List<IscsModelData> list = modelDataDao.selectByExampleWithBLOBs(example);
|
||||
return ModelMemory.create(list.get(0).getData());
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 模型数据的索引(页面id)
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public static class ModelMemoryIndex {
|
||||
//iscs 类型(扩展用,暂时默认值)
|
||||
private String type = ISCS_DEFAULT_TYPE;
|
||||
//iscs 系统(一级菜单)
|
||||
private String system;
|
||||
//iscs 视图(二级菜单)
|
||||
private String view;
|
||||
//iscs 场所(车站、变电所,等)(三级菜单)
|
||||
private String place;
|
||||
|
||||
public ModelMemoryIndex() {
|
||||
}
|
||||
|
||||
public ModelMemoryIndex(String system, String view, String place) {
|
||||
this.system = system;
|
||||
this.view = view;
|
||||
this.place = place;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ModelMemoryIndex that = (ModelMemoryIndex) o;
|
||||
return type.equals(that.type) && system.equals(that.system) && view.equals(that.view) && place.equals(that.place);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type, system, view, place);
|
||||
}
|
||||
}
|
||||
|
||||
public static final String ISCS_DEFAULT_TYPE = "FAST_TRAIN";
|
||||
}
|
Loading…
Reference in New Issue
Block a user