35 changed files with 1207 additions and 859 deletions
@ -0,0 +1,37 @@ |
|||
package com.yvan.logisticsEnv; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Data |
|||
public class EnvConfig implements Serializable { |
|||
|
|||
private MqttConfig mqtt; |
|||
|
|||
private MysqlConfig mysql; |
|||
|
|||
private RedisConfig redis; |
|||
|
|||
@Data |
|||
public static class MqttConfig { |
|||
private String brokerUrl; |
|||
private String username; |
|||
private String password; |
|||
private String websocket; |
|||
} |
|||
|
|||
@Data |
|||
public static class MysqlConfig { |
|||
private String jdbcUrl; |
|||
private String username; |
|||
private String password; |
|||
} |
|||
|
|||
@Data |
|||
public static class RedisConfig { |
|||
private String host; |
|||
private int port; |
|||
private String password; |
|||
} |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
package com.yvan.logisticsEnv; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
@Data |
|||
public class EnvPayload implements Serializable { |
|||
|
|||
private MqttConfig mqtt; |
|||
|
|||
@Data |
|||
public static class MqttConfig { |
|||
private String brokerUrl; |
|||
private String username; |
|||
private String password; |
|||
} |
|||
} |
|||
@ -1,29 +0,0 @@ |
|||
package com.yvan.logisticsEnv; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* 环境启动参数 |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
public class EnvStartParam { |
|||
|
|||
public String clientId; |
|||
|
|||
/** |
|||
* 是否虚拟仿真环境 |
|||
*/ |
|||
private boolean isVirtual; |
|||
|
|||
/** |
|||
* 时间倍速(仿真环境专用) |
|||
*/ |
|||
private Integer timeRate; |
|||
|
|||
/** |
|||
* Env环境配置 |
|||
*/ |
|||
private EnvPayload envPayload; |
|||
} |
|||
@ -1,88 +0,0 @@ |
|||
package com.yvan.logisticsEnv; |
|||
|
|||
import com.galaxis.rcs.common.enums.EnvStatus; |
|||
import com.google.common.collect.Lists; |
|||
import com.yvan.logisticsModel.ExecutorItem; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 物流仓储环境上下文 |
|||
*/ |
|||
@Getter |
|||
@Setter |
|||
public class LogisticsEnv { |
|||
/** |
|||
* 项目ID |
|||
*/ |
|||
public final String projectUUID; |
|||
|
|||
/** |
|||
* 环境ID |
|||
*/ |
|||
public final long envId; |
|||
|
|||
private EnvStartParam startParam; |
|||
|
|||
|
|||
/** |
|||
* 是否为虚拟环境 |
|||
*/ |
|||
private boolean isVirtual; |
|||
|
|||
/** |
|||
* 是否正在运行 |
|||
*/ |
|||
private boolean isRunning; |
|||
|
|||
/** |
|||
* 环境开始时间 |
|||
*/ |
|||
private long startTime; |
|||
|
|||
/** |
|||
* 环境停止时间 |
|||
*/ |
|||
private long stopTime; |
|||
|
|||
/** |
|||
* 时间流速倍率 |
|||
*/ |
|||
private int timeRate; |
|||
|
|||
public LogisticsEnv(String projectUUID, long envId) { |
|||
this.projectUUID = projectUUID; |
|||
this.envId = envId; |
|||
} |
|||
|
|||
public void start(EnvStartParam param) { |
|||
if (this.isRunning) { |
|||
throw new IllegalStateException("环境已经在运行中"); |
|||
} |
|||
this.startParam = param; |
|||
this.isRunning = true; |
|||
this.startTime = System.currentTimeMillis(); |
|||
this.stopTime = 0L; |
|||
this.timeRate = this.startParam.getTimeRate(); |
|||
} |
|||
|
|||
public long currentTimeMillis() { |
|||
if (!this.isVirtual) { |
|||
// 正式环境,返回系统当前时间
|
|||
return System.currentTimeMillis(); |
|||
} |
|||
if (!this.isRunning) { |
|||
return this.stopTime; |
|||
} |
|||
|
|||
long realCost = System.currentTimeMillis() - this.startTime; |
|||
return this.startTime + (realCost * this.timeRate); |
|||
} |
|||
|
|||
public Date getCurrentDate() { |
|||
return new Date(this.currentTimeMillis()); |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
package com.yvan.logisticsEnv; |
|||
|
|||
import java.util.HashMap; |
|||
import java.util.Map; |
|||
|
|||
public class LogisticsEnvManager { |
|||
|
|||
Map<String, LogisticsEnv> envs = new HashMap<>(); |
|||
|
|||
/** |
|||
* 启动参数 |
|||
*/ |
|||
public void startEnv(EnvStartParam param) { |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 复制环境, 返回新环境ID |
|||
*/ |
|||
public String cloneEnv(String envId) { |
|||
throw new RuntimeException(); |
|||
} |
|||
|
|||
/** |
|||
* 重置环境 |
|||
*/ |
|||
public String resetEnv(String envId) { |
|||
throw new RuntimeException(); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.yvan.workbench.autoconfigure; |
|||
|
|||
import com.yvan.workbench.service.LccAutoStartService; |
|||
import com.yvan.workbench.service.LccMapService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.boot.autoconfigure.AutoConfigureOrder; |
|||
import org.springframework.boot.context.properties.EnableConfigurationProperties; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import org.springframework.core.Ordered; |
|||
|
|||
@Slf4j |
|||
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) |
|||
@Configuration |
|||
@EnableConfigurationProperties(LccConfigProperties.class) |
|||
public class LccAutoConfiguration { |
|||
@Bean |
|||
public LccConfigProperties lccConfigProperties() { |
|||
return new LccConfigProperties(); |
|||
} |
|||
|
|||
@Bean |
|||
public LccAutoStartService lccAutoStartService() { |
|||
return new LccAutoStartService(this.lccConfigProperties()); |
|||
} |
|||
|
|||
@Bean |
|||
public LccMapService lccMapService() { |
|||
return new LccMapService(this.lccConfigProperties()); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
package com.yvan.workbench.autoconfigure; |
|||
|
|||
import lombok.Data; |
|||
import org.springframework.boot.context.properties.ConfigurationProperties; |
|||
|
|||
@Data |
|||
@ConfigurationProperties(prefix = LccConfigProperties.PREFIX) |
|||
public class LccConfigProperties { |
|||
public static final String PREFIX = "lcc"; |
|||
private String location; |
|||
private AutoStartItem[] autoStart; |
|||
|
|||
@Data |
|||
public static class AutoStartItem { |
|||
private String projectUuid; |
|||
private Long envId; |
|||
} |
|||
} |
|||
@ -1,6 +1,15 @@ |
|||
package com.yvan.workbench.controller; |
|||
|
|||
public class LccController { |
|||
|
|||
import com.yvan.workbench.SpringContext; |
|||
import com.yvan.workbench.service.LccMapService; |
|||
import org.clever.core.model.response.R; |
|||
|
|||
/** |
|||
* /api/workbench/LccController@get1 |
|||
*/ |
|||
public class LccController { |
|||
public static R<?> getAllProjects() { |
|||
var mapService = SpringContext.HOLDER.getBean(LccMapService.class); |
|||
return R.success(mapService.getAllProjects()); |
|||
} |
|||
} |
|||
|
|||
@ -1,34 +0,0 @@ |
|||
package com.yvan.workbench.model.entity; |
|||
|
|||
import lombok.Data; |
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* (lcc_model_floor) |
|||
*/ |
|||
@Data |
|||
public class LccModelFloor implements Serializable { |
|||
/** */ |
|||
private Long id; |
|||
/** 项目编号 */ |
|||
private String projectUuid; |
|||
/** 项目版本 */ |
|||
private Long projectVersion; |
|||
/** 环境ID */ |
|||
private Long envId; |
|||
/** 楼层编号 */ |
|||
private String catalogCode; |
|||
/** 楼层数据 */ |
|||
private String items; |
|||
/** */ |
|||
private Boolean autoStart; |
|||
/** 创建时间,默认为当前时间 */ |
|||
private Date createAt; |
|||
/** 创建人 */ |
|||
private String createBy; |
|||
/** 最后更新时间,默认为当前时间,并在更新时自动更新 */ |
|||
private Date updateAt; |
|||
/** 更新人 */ |
|||
private String updateBy; |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
package com.yvan.workbench.model.entity; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* (lcc_model_world) |
|||
*/ |
|||
@Data |
|||
public class LccModelWorld implements Serializable { |
|||
/** */ |
|||
private Long id; |
|||
/** 项目编号 */ |
|||
private String projectUuid; |
|||
/** 项目标题 */ |
|||
private String projectLabel; |
|||
/** 项目版本 */ |
|||
private Long projectVersion; |
|||
/** 所在服务器 */ |
|||
private String server; |
|||
/** 目录数据 */ |
|||
private String directoryData; |
|||
/** 其他数据 */ |
|||
private String otherData; |
|||
/** 创建时间,默认为当前时间 */ |
|||
private Date createAt; |
|||
/** 创建人 */ |
|||
private String createBy; |
|||
/** 最后更新时间,默认为当前时间,并在更新时自动更新 */ |
|||
private Date updateAt; |
|||
/** 更新人 */ |
|||
private String updateBy; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.yvan.workbench.model.entity; |
|||
|
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public class LccProject { |
|||
private String projectUuid; |
|||
private String projectLabel; |
|||
private String projectFileLocation; |
|||
private CatalogGroup[] directoryData; |
|||
private Map<String, Object> otherData; |
|||
|
|||
@Data |
|||
public static class CatalogGroup { |
|||
private String label; |
|||
private CatalogItem[] items; |
|||
} |
|||
|
|||
@Data |
|||
public static class CatalogItem { |
|||
private String catalogCode; |
|||
private String label; |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.yvan.workbench.model.entity; |
|||
|
|||
import com.yvan.logisticsEnv.EnvConfig; |
|||
import lombok.Data; |
|||
|
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public class LccProjectEnv { |
|||
private Long envId; |
|||
private String envName; |
|||
private Boolean isVirtual; |
|||
private EnvConfig envConfig; |
|||
private String fileLocation; |
|||
} |
|||
@ -1,80 +0,0 @@ |
|||
package com.yvan.workbench.model.query; |
|||
|
|||
import static com.querydsl.core.types.PathMetadataFactory.*; |
|||
import com.querydsl.core.types.dsl.*; |
|||
import com.querydsl.core.types.*; |
|||
import com.querydsl.sql.*; |
|||
import java.sql.Types; |
|||
import com.yvan.workbench.model.entity.LccModelFloor; |
|||
import java.util.Date; |
|||
|
|||
/** |
|||
* (lcc_model_floor) |
|||
*/ |
|||
@SuppressWarnings("ALL") |
|||
public class QLccModelFloor extends RelationalPathBase<LccModelFloor> { |
|||
/** lcc_model_floor表 */ |
|||
public static final QLccModelFloor lccModelFloor = new QLccModelFloor("lcc_model_floor"); |
|||
|
|||
/** */ |
|||
public final NumberPath<Long> id = createNumber("id", Long.class); |
|||
/** 项目编号 */ |
|||
public final StringPath projectUuid = createString("projectUuid"); |
|||
/** 项目版本 */ |
|||
public final NumberPath<Long> projectVersion = createNumber("projectVersion", Long.class); |
|||
/** 环境ID */ |
|||
public final NumberPath<Long> envId = createNumber("envId", Long.class); |
|||
/** 楼层编号 */ |
|||
public final StringPath catalogCode = createString("catalogCode"); |
|||
/** 楼层数据 */ |
|||
public final StringPath items = createString("items"); |
|||
/** */ |
|||
public final BooleanPath autoStart = createBoolean("autoStart"); |
|||
/** 创建时间,默认为当前时间 */ |
|||
public final DateTimePath<Date> createAt = createDateTime("createAt", Date.class); |
|||
/** 创建人 */ |
|||
public final StringPath createBy = createString("createBy"); |
|||
/** 最后更新时间,默认为当前时间,并在更新时自动更新 */ |
|||
public final DateTimePath<Date> updateAt = createDateTime("updateAt", Date.class); |
|||
/** 更新人 */ |
|||
public final StringPath updateBy = createString("updateBy"); |
|||
|
|||
public QLccModelFloor(String variable) { |
|||
super(LccModelFloor.class, forVariable(variable), "rcs2_tw_zhanghui", "lcc_model_floor"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelFloor(String variable, String schema, String table) { |
|||
super(LccModelFloor.class, forVariable(variable), schema, table); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelFloor(String variable, String schema) { |
|||
super(LccModelFloor.class, forVariable(variable), schema, "lcc_model_floor"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelFloor(Path<? extends LccModelFloor> path) { |
|||
super(path.getType(), path.getMetadata(), "rcs2_tw_zhanghui", "lcc_model_floor"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelFloor(PathMetadata metadata) { |
|||
super(LccModelFloor.class, metadata, "rcs2_tw_zhanghui", "lcc_model_floor"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
private void addMetadata() { |
|||
addMetadata(id, ColumnMetadata.named("id").withIndex(1).ofType(Types.BIGINT).withSize(19)); |
|||
addMetadata(projectUuid, ColumnMetadata.named("project_uuid").withIndex(2).ofType(Types.VARCHAR).withSize(36)); |
|||
addMetadata(projectVersion, ColumnMetadata.named("project_version").withIndex(3).ofType(Types.BIGINT).withSize(19)); |
|||
addMetadata(envId, ColumnMetadata.named("env_id").withIndex(4).ofType(Types.BIGINT).withSize(19)); |
|||
addMetadata(catalogCode, ColumnMetadata.named("catalogCode").withIndex(5).ofType(Types.VARCHAR).withSize(255)); |
|||
addMetadata(items, ColumnMetadata.named("items").withIndex(6).ofType(Types.LONGVARCHAR).withSize(16777215)); |
|||
addMetadata(autoStart, ColumnMetadata.named("auto_start").withIndex(7).ofType(Types.BIT).withSize(3)); |
|||
addMetadata(createAt, ColumnMetadata.named("create_at").withIndex(8).ofType(Types.TIMESTAMP)); |
|||
addMetadata(createBy, ColumnMetadata.named("create_by").withIndex(9).ofType(Types.VARCHAR).withSize(255)); |
|||
addMetadata(updateAt, ColumnMetadata.named("update_at").withIndex(10).ofType(Types.TIMESTAMP)); |
|||
addMetadata(updateBy, ColumnMetadata.named("update_by").withIndex(11).ofType(Types.VARCHAR).withSize(255)); |
|||
} |
|||
} |
|||
@ -1,86 +0,0 @@ |
|||
package com.yvan.workbench.model.query; |
|||
|
|||
import com.querydsl.core.types.Path; |
|||
import com.querydsl.core.types.PathMetadata; |
|||
import com.querydsl.core.types.dsl.DateTimePath; |
|||
import com.querydsl.core.types.dsl.NumberPath; |
|||
import com.querydsl.core.types.dsl.StringPath; |
|||
import com.querydsl.sql.ColumnMetadata; |
|||
import com.querydsl.sql.RelationalPathBase; |
|||
import com.yvan.workbench.model.entity.LccModelWorld; |
|||
|
|||
import java.sql.Types; |
|||
import java.util.Date; |
|||
|
|||
import static com.querydsl.core.types.PathMetadataFactory.forVariable; |
|||
|
|||
/** |
|||
* (lcc_model_world) |
|||
*/ |
|||
@SuppressWarnings("ALL") |
|||
public class QLccModelWorld extends RelationalPathBase<LccModelWorld> { |
|||
/** lcc_model_world表 */ |
|||
public static final QLccModelWorld lccModelWorld = new QLccModelWorld("lcc_model_world"); |
|||
|
|||
/** */ |
|||
public final NumberPath<Long> id = createNumber("id", Long.class); |
|||
/** 项目编号 */ |
|||
public final StringPath projectUuid = createString("projectUuid"); |
|||
/** 项目标题 */ |
|||
public final StringPath projectLabel = createString("projectLabel"); |
|||
/** 项目版本 */ |
|||
public final NumberPath<Long> projectVersion = createNumber("projectVersion", Long.class); |
|||
/** 所在服务器 */ |
|||
public final StringPath server = createString("server"); |
|||
/** 目录数据 */ |
|||
public final StringPath directoryData = createString("directoryData"); |
|||
/** 其他数据 */ |
|||
public final StringPath otherData = createString("otherData"); |
|||
/** 创建时间,默认为当前时间 */ |
|||
public final DateTimePath<Date> createAt = createDateTime("createAt", Date.class); |
|||
/** 创建人 */ |
|||
public final StringPath createBy = createString("createBy"); |
|||
/** 最后更新时间,默认为当前时间,并在更新时自动更新 */ |
|||
public final DateTimePath<Date> updateAt = createDateTime("updateAt", Date.class); |
|||
/** 更新人 */ |
|||
public final StringPath updateBy = createString("updateBy"); |
|||
|
|||
public QLccModelWorld(String variable) { |
|||
super(LccModelWorld.class, forVariable(variable), "test", "lcc_model_world"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelWorld(String variable, String schema, String table) { |
|||
super(LccModelWorld.class, forVariable(variable), schema, table); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelWorld(String variable, String schema) { |
|||
super(LccModelWorld.class, forVariable(variable), schema, "lcc_model_world"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelWorld(Path<? extends LccModelWorld> path) { |
|||
super(path.getType(), path.getMetadata(), "test", "lcc_model_world"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
public QLccModelWorld(PathMetadata metadata) { |
|||
super(LccModelWorld.class, metadata, "test", "lcc_model_world"); |
|||
addMetadata(); |
|||
} |
|||
|
|||
private void addMetadata() { |
|||
addMetadata(id, ColumnMetadata.named("id").withIndex(1).ofType(Types.BIGINT).withSize(19)); |
|||
addMetadata(projectUuid, ColumnMetadata.named("project_uuid").withIndex(2).ofType(Types.VARCHAR).withSize(36)); |
|||
addMetadata(projectLabel, ColumnMetadata.named("project_label").withIndex(3).ofType(Types.VARCHAR).withSize(255)); |
|||
addMetadata(projectVersion, ColumnMetadata.named("project_version").withIndex(4).ofType(Types.BIGINT).withSize(19)); |
|||
addMetadata(server, ColumnMetadata.named("server").withIndex(5).ofType(Types.VARCHAR).withSize(255)); |
|||
addMetadata(directoryData, ColumnMetadata.named("directory_data").withIndex(6).ofType(Types.LONGVARCHAR).withSize(65535)); |
|||
addMetadata(otherData, ColumnMetadata.named("other_data").withIndex(7).ofType(Types.LONGVARCHAR).withSize(65535)); |
|||
addMetadata(createAt, ColumnMetadata.named("create_at").withIndex(8).ofType(Types.TIMESTAMP)); |
|||
addMetadata(createBy, ColumnMetadata.named("create_by").withIndex(9).ofType(Types.VARCHAR).withSize(255)); |
|||
addMetadata(updateAt, ColumnMetadata.named("update_at").withIndex(10).ofType(Types.TIMESTAMP)); |
|||
addMetadata(updateBy, ColumnMetadata.named("update_by").withIndex(11).ofType(Types.VARCHAR).withSize(255)); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
package com.yvan.workbench.service; |
|||
|
|||
import com.galaxis.rcs.RCSService; |
|||
import com.google.common.base.Strings; |
|||
import com.yvan.logisticsModel.LogisticsRuntimeService; |
|||
import com.yvan.workbench.autoconfigure.LccConfigProperties; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.context.SmartLifecycle; |
|||
|
|||
@Slf4j |
|||
public class LccAutoStartService implements SmartLifecycle { |
|||
private final LccConfigProperties lccConfigProperties; |
|||
|
|||
public LccAutoStartService(LccConfigProperties lccConfigProperties) { |
|||
this.lccConfigProperties = lccConfigProperties; |
|||
} |
|||
|
|||
@Override |
|||
public void start() { |
|||
var autoStartItems = this.lccConfigProperties.getAutoStart(); |
|||
for (var item : autoStartItems) { |
|||
String projectUUID = item.getProjectUuid(); |
|||
Long envId = item.getEnvId(); |
|||
|
|||
if (Strings.isNullOrEmpty(projectUUID) || envId == null || envId <= 0) { |
|||
log.warn("Skipping auto start for project UUID '{}' and env ID '{}', invalid configuration.", projectUUID, envId); |
|||
continue; // 跳过无效的配置
|
|||
} |
|||
|
|||
RCSService.projectStart(projectUUID, envId); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void stop() { |
|||
LogisticsRuntimeService.INSTANCE.stopAll(); |
|||
} |
|||
|
|||
@Override |
|||
public boolean isRunning() { |
|||
return LogisticsRuntimeService.INSTANCE.isRunning(); |
|||
} |
|||
} |
|||
@ -0,0 +1,291 @@ |
|||
package com.yvan.workbench.service; |
|||
|
|||
import com.google.common.base.Joiner; |
|||
import com.google.common.base.Strings; |
|||
import com.google.common.collect.Lists; |
|||
import com.yvan.workbench.autoconfigure.LccConfigProperties; |
|||
import com.yvan.workbench.model.entity.LccProject; |
|||
import com.yvan.workbench.model.entity.LccProjectEnv; |
|||
import lombok.SneakyThrows; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.apache.commons.io.FileUtils; |
|||
import org.apache.commons.io.FilenameUtils; |
|||
import org.clever.core.mapper.JacksonMapper; |
|||
|
|||
import java.io.File; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
|
|||
@Slf4j |
|||
public class LccMapService { |
|||
private final LccConfigProperties config; |
|||
|
|||
public LccMapService(LccConfigProperties lccConfigProperties) { |
|||
this.config = lccConfigProperties; |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public LccProject getProjectById(String projectUuid) { |
|||
checkProjectUuid(projectUuid, false); |
|||
var projectFile = new File(this.config.getLocation() + "/" + projectUuid + "/project.json"); |
|||
|
|||
if (!projectFile.exists() || !projectFile.isFile()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getProjectById() - project '%s' does not exist or is not a file", projectFile.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
log.info("load project file: {}", projectFile.getAbsolutePath()); |
|||
String content = Joiner.on("\n").join(FileUtils.readLines(projectFile, StandardCharsets.UTF_8)); |
|||
var project = JacksonMapper.getInstance().fromJson(content, LccProject.class); |
|||
project.setProjectFileLocation( |
|||
FilenameUtils.normalize(projectFile.getAbsolutePath(), true) |
|||
); |
|||
return project; |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public LccProjectEnv getEnvById(String projectUuid, Long envId) { |
|||
checkProjectUuid(projectUuid, false); |
|||
var projectFile = new File(this.config.getLocation() + "/" + projectUuid + "/envs/" + envId + ".json"); |
|||
if (!projectFile.exists() || !projectFile.isFile()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getEnvById() - env '%s' does not exist or is not a file", projectFile.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
log.info("load project file: {}", projectFile.getAbsolutePath()); |
|||
String content = Joiner.on("\n").join(FileUtils.readLines(projectFile, StandardCharsets.UTF_8)); |
|||
if (Strings.isNullOrEmpty(content)) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getEnvById() - env '%s' content is empty", projectFile.getAbsolutePath()) |
|||
); |
|||
} |
|||
if (!content.contains("envConfig")) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getEnvById() - env '%s' content is not a valid LccProjectEnv", projectFile.getAbsolutePath()) |
|||
); |
|||
} |
|||
var envInfo = JacksonMapper.getInstance().fromJson(content, LccProjectEnv.class); |
|||
envInfo.setFileLocation( |
|||
FilenameUtils.normalize(projectFile.getAbsolutePath(), true) |
|||
); |
|||
return envInfo; |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public List<LccProject> getAllProjects() { |
|||
var mapLoc = new File(this.config.getLocation()); |
|||
|
|||
// 扫描 mapLoc 目录下所有的文件夹,并且文件夹中包含有 project.json 文件存在,就讲她反序列化为 LccProject 对象
|
|||
if (!mapLoc.exists() || !mapLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getAllProjects() - mapLoc '%s' does not exist or is not a directory", mapLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
List<LccProject> list = Lists.newArrayList(); |
|||
for (File projectFolder : Objects.requireNonNull(mapLoc.listFiles())) { |
|||
if (projectFolder.isDirectory()) { |
|||
File projectFile = new File(projectFolder, "project.json"); |
|||
if (projectFile.exists() && projectFile.isFile()) { |
|||
// 反序列化 project.json 文件为 LccProject 对象
|
|||
log.info("load project file: {}", projectFile.getAbsolutePath()); |
|||
String content = Joiner.on("\n").join(FileUtils.readLines(projectFile, StandardCharsets.UTF_8)); |
|||
if (Strings.isNullOrEmpty(content)) { |
|||
continue; |
|||
} |
|||
if (!content.contains("directoryData")) { |
|||
continue; |
|||
} |
|||
|
|||
var modelWorld = JacksonMapper.getInstance().fromJson(content, LccProject.class); |
|||
modelWorld.setProjectFileLocation( |
|||
FilenameUtils.normalize(projectFile.getAbsolutePath(), true) |
|||
); |
|||
list.add(modelWorld); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return list; |
|||
} |
|||
|
|||
public void checkProjectUuid(String projectUuid, boolean checkExists) { |
|||
// 检查项目编号是否符合规范
|
|||
if (Strings.isNullOrEmpty(projectUuid)) { |
|||
throw new RuntimeException("projectUuid cannot be null or empty"); |
|||
} |
|||
if (!projectUuid.matches("^[a-zA-Z0-9_\\-]+$")) { |
|||
throw new RuntimeException("projectUuid must be alphanumeric, underscores or hyphens"); |
|||
} |
|||
|
|||
// 检查项目文件名是否存在
|
|||
if (checkExists) { |
|||
var names = getAllProjectNames(); |
|||
if (names.contains(projectUuid)) { |
|||
throw new RuntimeException("projectUuid '" + projectUuid + "' has already exists, please use another one"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public void saveProject(LccProject project) { |
|||
// 检查项目编号是否符合规范
|
|||
checkProjectUuid(project.getProjectUuid(), false); |
|||
|
|||
// 检查项目目录是否存在
|
|||
var mapLoc = new File(this.config.getLocation()); |
|||
if (!mapLoc.exists() || !mapLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.saveProject() - mapLoc '%s' does not exist or is not a directory", mapLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
// 创建项目目录
|
|||
var projectDir = new File(mapLoc, project.getProjectUuid()); |
|||
if (!projectDir.exists()) { |
|||
projectDir.mkdirs(); |
|||
} |
|||
|
|||
// 这个字段不保存
|
|||
project.setProjectFileLocation(""); |
|||
|
|||
// 保存 project.json 文件
|
|||
var projectFile = new File(projectDir, "project.json"); |
|||
|
|||
// 如果 project.json 文件与 content 内容不一致,则跟新覆盖写入
|
|||
String contentOrigin = projectFile.exists() ? Joiner.on("\n").join(FileUtils.readLines(projectFile, StandardCharsets.UTF_8)) : ""; |
|||
String content = JacksonMapper.getInstance().toJsonPretty(project); |
|||
if (!content.equals(contentOrigin)) { |
|||
// 内容不一致时,更新项目的更新时间和更新人
|
|||
log.info("write project file: {}", projectFile.getAbsolutePath()); |
|||
FileUtils.writeStringToFile(projectFile, content, StandardCharsets.UTF_8); |
|||
} else { |
|||
log.info("project file no change, ignore write, path:{}", projectFile.getAbsolutePath()); |
|||
} |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public String loadFloor(String projectUuid, String catalogCode) { |
|||
// 检查项目编号/楼层编号是否符合规范, 防止注入漏洞
|
|||
checkProjectUuid(projectUuid, false); |
|||
checkProjectUuid(catalogCode, false); |
|||
|
|||
// 检查项目目录是否存在
|
|||
var mapLoc = new File(this.config.getLocation()); |
|||
if (!mapLoc.exists() || !mapLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.saveProject() - mapLoc '%s' does not exist or is not a directory", mapLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
// 创建项目目录
|
|||
var floorFile = new File(mapLoc, projectUuid + "/floor/" + catalogCode + ".json"); |
|||
if (!floorFile.exists() || !floorFile.isFile()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.loadFloor() - '%s' does not exist or is not a file", floorFile.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
log.info("load floor file: {}", floorFile.getAbsolutePath()); |
|||
String content = Joiner.on("\n").join(FileUtils.readLines(floorFile, StandardCharsets.UTF_8)); |
|||
if (Strings.isNullOrEmpty(content)) { |
|||
// 如果内容为空,则返回空数组
|
|||
content = "[]"; |
|||
} |
|||
return content; |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public void saveFloor(String projectUuid, String catalogCode, String items) { |
|||
// 检查项目编号/楼层编号是否符合规范, 防止注入漏洞
|
|||
checkProjectUuid(projectUuid, false); |
|||
checkProjectUuid(catalogCode, false); |
|||
|
|||
if (Strings.isNullOrEmpty(items)) { |
|||
items = "[]"; |
|||
} |
|||
|
|||
// 检查项目目录是否存在
|
|||
var mapLoc = new File(this.config.getLocation()); |
|||
if (!mapLoc.exists() || !mapLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.saveFloor() - mapLoc '%s' does not exist or is not a directory", mapLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
// 创建项目目录
|
|||
var floorDir = new File(mapLoc, projectUuid + "/floor"); |
|||
if (!floorDir.exists()) { |
|||
floorDir.mkdirs(); |
|||
} |
|||
|
|||
// 保存楼层数据到文件
|
|||
var floorFile = new File(floorDir, catalogCode + ".json"); |
|||
log.info("write floor file: {}", floorFile.getAbsolutePath()); |
|||
FileUtils.writeStringToFile(floorFile, items, StandardCharsets.UTF_8); |
|||
} |
|||
|
|||
@SneakyThrows |
|||
public List<LccProjectEnv> getAllEnv(String projectUuid) { |
|||
checkProjectUuid(projectUuid, false); |
|||
|
|||
var envLoc = new File(this.config.getLocation() + "/" + projectUuid + "/envs"); |
|||
|
|||
// 扫描 mapLoc 目录下所有的文件夹,并且文件夹中包含有 project.json 文件存在,就讲她反序列化为 LccProject 对象
|
|||
if (!envLoc.exists() || !envLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getAllProjects() - mapLoc '%s' does not exist or is not a directory", envLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
List<LccProjectEnv> list = Lists.newArrayList(); |
|||
for (File propFile : Objects.requireNonNull(envLoc.listFiles())) { |
|||
if (propFile.exists() && propFile.isFile() && propFile.getName().endsWith(".json")) { |
|||
// 反序列化 project.json 文件为 LccProject 对象
|
|||
log.info("load env file: {}", propFile.getAbsolutePath()); |
|||
String content = Joiner.on("\n").join(FileUtils.readLines(propFile, StandardCharsets.UTF_8)); |
|||
if (Strings.isNullOrEmpty(content)) { |
|||
continue; |
|||
} |
|||
if (!content.contains("envConfig")) { |
|||
continue; |
|||
} |
|||
|
|||
var envInfo = JacksonMapper.getInstance().fromJson(content, LccProjectEnv.class); |
|||
envInfo.setFileLocation( |
|||
FilenameUtils.normalize(propFile.getAbsolutePath(), true) |
|||
); |
|||
list.add(envInfo); |
|||
} |
|||
} |
|||
return list; |
|||
} |
|||
|
|||
|
|||
public List<String> getAllProjectNames() { |
|||
var mapLoc = new File(this.config.getLocation()); |
|||
|
|||
// 扫描 mapLoc 目录下所有的文件夹,并且文件夹中包含有 project.json 文件存在,就讲她反序列化为 LccProject 对象
|
|||
if (!mapLoc.exists() || !mapLoc.isDirectory()) { |
|||
throw new RuntimeException( |
|||
String.format("LccMapService.getAllProjects() - mapLoc '%s' does not exist or is not a directory", mapLoc.getAbsolutePath()) |
|||
); |
|||
} |
|||
|
|||
List<String> list = Lists.newArrayList(); |
|||
for (File projectFolder : Objects.requireNonNull(mapLoc.listFiles())) { |
|||
if (projectFolder.isDirectory()) { |
|||
File projectFile = new File(projectFolder, "project.json"); |
|||
if (projectFile.exists() && projectFile.isFile()) { |
|||
list.add(projectFolder.getName()); |
|||
} |
|||
} |
|||
} |
|||
return list; |
|||
} |
|||
|
|||
|
|||
} |
|||
Loading…
Reference in new issue