(improvement)(headless) Modify the headless module structure to api, core and server (#588)

Co-authored-by: jolunoluo
This commit is contained in:
LXW
2024-01-02 16:43:28 +08:00
committed by GitHub
parent af1c560cc4
commit e7f13572d7
352 changed files with 2296 additions and 2675 deletions

101
headless/server/pom.xml Normal file
View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tencent.supersonic</groupId>
<artifactId>headless</artifactId>
<version>${revision}</version>
</parent>
<artifactId>headless-server</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>headless-api</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.tencent.supersonic</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${alibaba.druid.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${org.testng.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,60 @@
package com.tencent.supersonic.headless.server.engineadapter;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserReplaceHelper;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.pojo.Constants;
import java.util.HashMap;
import java.util.Map;
public class ClickHouseAdaptor extends EngineAdaptor {
@Override
public String getDateFormat(String dateType, String dateFormat, String column) {
if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT_INT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "formatDateTime(toDate(parseDateTimeBestEffort(toString(%s))),'%Y-%m')".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "toMonday(toDate(parseDateTimeBestEffort(toString(%s))))".replace("%s", column);
} else {
return "toDate(parseDateTimeBestEffort(toString(%s)))".replace("%s", column);
}
} else if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "formatDateTime(toDate(%s),'%Y-%m')".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "toMonday(toDate(%s))".replace("%s", column);
} else {
return column;
}
}
return column;
}
@Override
public String getDbMetaQueryTpl() {
return " "
+ " select "
+ " name from system.databases "
+ " where name not in('_temporary_and_external_tables','benchmark','default','system');";
}
@Override
public String getTableMetaQueryTpl() {
return "select name from system.tables where database = '%s';";
}
@Override
public String functionNameCorrector(String sql) {
Map<String, String> functionMap = new HashMap<>();
functionMap.put("MONTH".toLowerCase(), "toMonth");
functionMap.put("DAY".toLowerCase(), "toDayOfMonth");
functionMap.put("YEAR".toLowerCase(), "toYear");
return SqlParserReplaceHelper.replaceFunction(sql, functionMap);
}
@Override
public String getColumnMetaQueryTpl() {
return "select name,type as dataType, comment from system.columns where database = '%s' and table='%s'";
}
}

View File

@@ -0,0 +1,15 @@
package com.tencent.supersonic.headless.server.engineadapter;
public abstract class EngineAdaptor {
public abstract String getDateFormat(String dateType, String dateFormat, String column);
public abstract String getColumnMetaQueryTpl();
public abstract String getDbMetaQueryTpl();
public abstract String getTableMetaQueryTpl();
public abstract String functionNameCorrector(String sql);
}

View File

@@ -0,0 +1,24 @@
package com.tencent.supersonic.headless.server.engineadapter;
import com.tencent.supersonic.headless.server.pojo.EngineTypeEnum;
import java.util.HashMap;
import java.util.Map;
public class EngineAdaptorFactory {
private static Map<String, EngineAdaptor> engineAdaptorMap;
static {
engineAdaptorMap = new HashMap<>();
engineAdaptorMap.put(EngineTypeEnum.CLICKHOUSE.getName(), new ClickHouseAdaptor());
engineAdaptorMap.put(EngineTypeEnum.MYSQL.getName(), new MysqlAdaptor());
engineAdaptorMap.put(EngineTypeEnum.H2.getName(), new H2Adaptor());
}
public static EngineAdaptor getEngineAdaptor(String engineType) {
return engineAdaptorMap.get(engineType);
}
}

View File

@@ -0,0 +1,56 @@
package com.tencent.supersonic.headless.server.engineadapter;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
public class H2Adaptor extends EngineAdaptor {
@Override
public String getDateFormat(String dateType, String dateFormat, String column) {
if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT_INT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "FORMATDATETIME(PARSEDATETIME(%s, 'yyyyMMdd'),'yyyy-MM')".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "DATE_TRUNC('week',%s)".replace("%s", column);
} else {
return "FORMATDATETIME(PARSEDATETIME(%s, 'yyyyMMdd'),'yyyy-MM-dd')".replace("%s", column);
}
} else if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "FORMATDATETIME(PARSEDATETIME(%s, 'yyyy-MM-dd'),'yyyy-MM') ".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "DATE_TRUNC('week',%s)".replace("%s", column);
} else {
return column;
}
}
return column;
}
@Override
public String getColumnMetaQueryTpl() {
return "SELECT COLUMN_NAME AS name, "
+ " case DATA_TYPE"
+ " when '12' then 'varchar'"
+ " when '-5' then 'integer'"
+ " when '8' then 'double'"
+ " end AS dataType"
+ " FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA ='%s' AND TABLE_NAME = '%s'";
}
@Override
public String getDbMetaQueryTpl() {
return "SELECT DISTINCT TABLE_SCHEMA as name FROM INFORMATION_SCHEMA.TABLES WHERE STORAGE_TYPE = 'MEMORY'";
}
@Override
public String getTableMetaQueryTpl() {
return "SELECT TABLE_NAME as name FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE STORAGE_TYPE = 'MEMORY' AND TABLE_SCHEMA = '%s'";
}
@Override
public String functionNameCorrector(String sql) {
return sql;
}
}

View File

@@ -0,0 +1,57 @@
package com.tencent.supersonic.headless.server.engineadapter;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.pojo.Constants;
public class MysqlAdaptor extends EngineAdaptor {
/**
* transform YYYYMMDD to YYYY-MM-DD YYYY-MM YYYY-MM-DD(MONDAY)
*/
@Override
public String getDateFormat(String dateType, String dateFormat, String column) {
if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT_INT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "DATE_FORMAT(%s, '%Y-%m')".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "DATE_FORMAT(DATE_SUB(%s, INTERVAL (DAYOFWEEK(%s) - 2) DAY), '%Y-%m-%d')".replace("%s", column);
} else {
return "date_format(str_to_date(%s, '%Y%m%d'),'%Y-%m-%d')".replace("%s", column);
}
} else if (dateFormat.equalsIgnoreCase(Constants.DAY_FORMAT)) {
if (TimeDimensionEnum.MONTH.name().equalsIgnoreCase(dateType)) {
return "DATE_FORMAT(%s, '%Y-%m') ".replace("%s", column);
} else if (TimeDimensionEnum.WEEK.name().equalsIgnoreCase(dateType)) {
return "DATE_FORMAT(DATE_SUB(%s, INTERVAL (DAYOFWEEK(%s) - 2) DAY), '%Y-%m-%d')".replace("%s", column);
} else {
return column;
}
}
return column;
}
@Override
public String getDbMetaQueryTpl() {
return "select distinct TABLE_SCHEMA as name from information_schema.tables "
+ "where TABLE_SCHEMA not in ('information_schema','mysql','performance_schema','sys');";
}
@Override
public String getTableMetaQueryTpl() {
return "select TABLE_NAME as name from information_schema.tables where TABLE_SCHEMA = '%s';";
}
@Override
public String functionNameCorrector(String sql) {
return sql;
}
@Override
public String getColumnMetaQueryTpl() {
return "SELECT COLUMN_NAME as name, DATA_TYPE as dataType, COLUMN_COMMENT as comment "
+ "FROM information_schema.columns WHERE table_schema ='%s' AND table_name = '%s'";
}
}

View File

@@ -0,0 +1,69 @@
package com.tencent.supersonic.headless.server.listener;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.enums.DictWordType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.util.ComponentFactory;
import com.tencent.supersonic.common.util.embedding.EmbeddingQuery;
import com.tencent.supersonic.common.util.embedding.S2EmbeddingStore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
@Slf4j
public class MetaEmbeddingListener implements ApplicationListener<DataEvent> {
public static final String COLLECTION_NAME = "meta_collection";
private S2EmbeddingStore s2EmbeddingStore = ComponentFactory.getS2EmbeddingStore();
@Value("${embedding.operation.sleep.time:3000}")
private Integer embeddingOperationSleepTime;
@Async
@Override
public void onApplicationEvent(DataEvent event) {
if (CollectionUtils.isEmpty(event.getDataItems())) {
return;
}
List<EmbeddingQuery> embeddingQueries = event.getDataItems()
.stream()
.map(dataItem -> {
EmbeddingQuery embeddingQuery = new EmbeddingQuery();
embeddingQuery.setQueryId(
dataItem.getId().toString() + DictWordType.NATURE_SPILT + dataItem.getType().getName());
embeddingQuery.setQuery(dataItem.getName());
Map meta = JSONObject.parseObject(JSONObject.toJSONString(dataItem), Map.class);
embeddingQuery.setMetadata(meta);
embeddingQuery.setQueryEmbedding(null);
return embeddingQuery;
}).collect(Collectors.toList());
if (CollectionUtils.isEmpty(embeddingQueries)) {
return;
}
try {
Thread.sleep(embeddingOperationSleepTime);
} catch (InterruptedException e) {
log.error("", e);
}
s2EmbeddingStore.addCollection(COLLECTION_NAME);
if (event.getEventType().equals(EventType.ADD)) {
s2EmbeddingStore.addQuery(COLLECTION_NAME, embeddingQueries);
} else if (event.getEventType().equals(EventType.DELETE)) {
s2EmbeddingStore.deleteQuery(COLLECTION_NAME, embeddingQueries);
} else if (event.getEventType().equals(EventType.UPDATE)) {
s2EmbeddingStore.deleteQuery(COLLECTION_NAME, embeddingQueries);
s2EmbeddingStore.addQuery(COLLECTION_NAME, embeddingQueries);
}
}
}

View File

@@ -0,0 +1,30 @@
package com.tencent.supersonic.headless.server.manager;
import com.tencent.supersonic.headless.common.server.enums.IdentifyType;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.utils.DimensionConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class DimensionYamlManager {
public static List<DimensionYamlTpl> convert2DimensionYaml(List<DimensionResp> dimensions) {
if (CollectionUtils.isEmpty(dimensions)) {
return new ArrayList<>();
}
return dimensions.stream()
.filter(dimension -> !dimension.getType().equalsIgnoreCase(IdentifyType.primary.name()))
.map(DimensionConverter::convert2DimensionYamlTpl).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,27 @@
package com.tencent.supersonic.headless.server.manager;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.server.pojo.yaml.MetricYamlTpl;
import com.tencent.supersonic.headless.server.utils.MetricConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class MetricYamlManager {
public static List<MetricYamlTpl> convert2YamlObj(List<MetricResp> metrics) {
List<MetricYamlTpl> metricYamlTpls = new ArrayList<>();
for (MetricResp metric : metrics) {
MetricYamlTpl metricYamlTpl = MetricConverter.convert2MetricYamlTpl(metric);
metricYamlTpls.add(metricYamlTpl);
}
return metricYamlTpls;
}
}

View File

@@ -0,0 +1,98 @@
package com.tencent.supersonic.headless.server.manager;
import com.tencent.supersonic.headless.common.server.enums.ModelSourceType;
import com.tencent.supersonic.headless.common.server.pojo.Dim;
import com.tencent.supersonic.headless.common.server.pojo.Identify;
import com.tencent.supersonic.headless.common.server.pojo.Measure;
import com.tencent.supersonic.headless.common.server.pojo.ModelDetail;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DataModelYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionTimeTypeParamsTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.IdentifyYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.MeasureYamlTpl;
import com.tencent.supersonic.headless.server.engineadapter.EngineAdaptor;
import com.tencent.supersonic.headless.server.engineadapter.EngineAdaptorFactory;
import com.tencent.supersonic.headless.server.pojo.DatasourceQueryEnum;
import com.tencent.supersonic.headless.server.utils.SysTimeDimensionBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ModelYamlManager {
public static DataModelYamlTpl convert2YamlObj(ModelResp modelResp, DatabaseResp databaseResp) {
ModelDetail modelDetail = modelResp.getModelDetail();
EngineAdaptor engineAdaptor = EngineAdaptorFactory.getEngineAdaptor(databaseResp.getType());
SysTimeDimensionBuilder.addSysTimeDimension(modelDetail.getDimensions(), engineAdaptor);
addInterCntMetric(modelResp.getBizName(), modelDetail);
DataModelYamlTpl dataModelYamlTpl = new DataModelYamlTpl();
BeanUtils.copyProperties(modelDetail, dataModelYamlTpl);
dataModelYamlTpl.setIdentifiers(modelDetail.getIdentifiers().stream().map(ModelYamlManager::convert)
.collect(Collectors.toList()));
dataModelYamlTpl.setDimensions(modelDetail.getDimensions().stream().map(ModelYamlManager::convert)
.collect(Collectors.toList()));
dataModelYamlTpl.setMeasures(modelDetail.getMeasures().stream().map(ModelYamlManager::convert)
.collect(Collectors.toList()));
dataModelYamlTpl.setName(modelResp.getBizName());
dataModelYamlTpl.setSourceId(modelResp.getDatabaseId());
dataModelYamlTpl.setModelSourceTypeEnum(ModelSourceType.of(modelResp.getSourceType()));
if (modelDetail.getQueryType().equalsIgnoreCase(DatasourceQueryEnum.SQL_QUERY.getName())) {
dataModelYamlTpl.setSqlQuery(modelDetail.getSqlQuery());
} else {
dataModelYamlTpl.setTableQuery(modelDetail.getTableQuery());
}
return dataModelYamlTpl;
}
public static DimensionYamlTpl convert(Dim dim) {
DimensionYamlTpl dimensionYamlTpl = new DimensionYamlTpl();
BeanUtils.copyProperties(dim, dimensionYamlTpl);
dimensionYamlTpl.setName(dim.getBizName());
if (Objects.isNull(dimensionYamlTpl.getExpr())) {
dimensionYamlTpl.setExpr(dim.getBizName());
}
if (dim.getTypeParams() != null) {
DimensionTimeTypeParamsTpl dimensionTimeTypeParamsTpl = new DimensionTimeTypeParamsTpl();
dimensionTimeTypeParamsTpl.setIsPrimary(dim.getTypeParams().getIsPrimary());
dimensionTimeTypeParamsTpl.setTimeGranularity(dim.getTypeParams().getTimeGranularity());
dimensionYamlTpl.setTypeParams(dimensionTimeTypeParamsTpl);
}
return dimensionYamlTpl;
}
public static MeasureYamlTpl convert(Measure measure) {
MeasureYamlTpl measureYamlTpl = new MeasureYamlTpl();
BeanUtils.copyProperties(measure, measureYamlTpl);
measureYamlTpl.setName(measure.getBizName());
return measureYamlTpl;
}
public static IdentifyYamlTpl convert(Identify identify) {
IdentifyYamlTpl identifyYamlTpl = new IdentifyYamlTpl();
identifyYamlTpl.setName(identify.getBizName());
identifyYamlTpl.setType(identify.getType());
return identifyYamlTpl;
}
private static void addInterCntMetric(String datasourceEnName, ModelDetail datasourceDetail) {
Measure measure = new Measure();
measure.setExpr("1");
if (!CollectionUtils.isEmpty(datasourceDetail.getIdentifiers())) {
measure.setExpr(datasourceDetail.getIdentifiers().get(0).getBizName());
}
measure.setAgg("count");
measure.setBizName(String.format("%s_%s", datasourceEnName, "internal_cnt"));
measure.setCreateMetric("true");
datasourceDetail.getMeasures().add(measure);
}
}

View File

@@ -0,0 +1,41 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_app")
public class AppDO {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String description;
private String config;
private Date endDate;
private Integer qps;
private String owner;
private Integer status;
private String appSecret;
private String createdBy;
private String updatedBy;
private Date createdAt;
private Date updatedAt;
}

View File

@@ -0,0 +1,64 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 收藏项表
* </p>
*
* @author yannsu
* @since 2023-11-09 03:49:33
*/
@Getter
@Setter
@TableName("s2_collect")
public class CollectDO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 收藏项ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 收藏的类型
*/
@TableField("type")
private String type;
/**
* 收藏人
*/
@TableField("username")
private String username;
/**
* 收藏ID
*/
@TableField("collect_id")
private Long collectId;
/**
* 创建时间
*/
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,257 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import java.util.Date;
public class DatabaseDO {
/**
*
*/
private Long id;
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
/**
*
*/
private String version;
/**
* 类型 mysql,clickhouse,tdw
*/
private String type;
/**
* 创建时间
*/
private Date createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 更新人
*/
private String updatedBy;
/**
*
*/
private String admin;
/**
*
*/
private String viewer;
/**
* 配置信息
*/
private String config;
/**
*
* @return id
*/
public Long getId() {
return id;
}
/**
*
* @param id
*/
public void setId(Long id) {
this.id = id;
}
/**
* 名称
* @return name 名称
*/
public String getName() {
return name;
}
/**
* 名称
* @param name 名称
*/
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
/**
* 描述
* @return description 描述
*/
public String getDescription() {
return description;
}
/**
* 描述
* @param description 描述
*/
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
/**
*
* @return version
*/
public String getVersion() {
return version;
}
/**
*
* @param version
*/
public void setVersion(String version) {
this.version = version == null ? null : version.trim();
}
/**
* 类型 mysql,clickhouse,tdw
* @return type 类型 mysql,clickhouse,tdw
*/
public String getType() {
return type;
}
/**
* 类型 mysql,clickhouse,tdw
* @param type 类型 mysql,clickhouse,tdw
*/
public void setType(String type) {
this.type = type == null ? null : type.trim();
}
/**
* 创建时间
* @return created_at 创建时间
*/
public Date getCreatedAt() {
return createdAt;
}
/**
* 创建时间
* @param createdAt 创建时间
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/**
* 创建人
* @return created_by 创建人
*/
public String getCreatedBy() {
return createdBy;
}
/**
* 创建人
* @param createdBy 创建人
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy == null ? null : createdBy.trim();
}
/**
* 更新时间
* @return updated_at 更新时间
*/
public Date getUpdatedAt() {
return updatedAt;
}
/**
* 更新时间
* @param updatedAt 更新时间
*/
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
/**
* 更新人
* @return updated_by 更新人
*/
public String getUpdatedBy() {
return updatedBy;
}
/**
* 更新人
* @param updatedBy 更新人
*/
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
}
/**
*
* @return admin
*/
public String getAdmin() {
return admin;
}
/**
*
* @param admin
*/
public void setAdmin(String admin) {
this.admin = admin == null ? null : admin.trim();
}
/**
*
* @return viewer
*/
public String getViewer() {
return viewer;
}
/**
*
* @param viewer
*/
public void setViewer(String viewer) {
this.viewer = viewer == null ? null : viewer.trim();
}
/**
* 配置信息
* @return config 配置信息
*/
public String getConfig() {
return config;
}
/**
* 配置信息
* @param config 配置信息
*/
public void setConfig(String config) {
this.config = config == null ? null : config.trim();
}
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import lombok.Data;
@Data
public class DateInfoDO {
private Long id;
private String type;
private Long itemId;
private String dateFormat;
private String startDate;
private String endDate;
private String unavailableDateList;
private String createdBy;
private String updatedBy;
private String datePeriod;
}

View File

@@ -0,0 +1,54 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_dimension")
public class DimensionDO {
@TableId(type = IdType.AUTO)
private Long id;
private Long modelId;
private String name;
private String bizName;
private String description;
private Integer status;
private Integer sensitiveLevel;
private String type;
private Date createdAt;
private String createdBy;
private Date updatedAt;
private String updatedBy;
private String semanticType;
private String alias;
private String defaultValues;
private String dimValueMaps;
private String typeParams;
private String expr;
private String dataType;
private int isTag;
}

View File

@@ -0,0 +1,84 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_domain")
public class DomainDO {
/**
* 自增ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 主题域名称
*/
private String name;
/**
* 内部名称
*/
private String bizName;
/**
* 父主题域ID
*/
private Long parentId;
/**
* 主题域状态
*/
private Integer status;
/**
* 创建时间
*/
private Date createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 更新人
*/
private String updatedBy;
/**
* 主题域管理员
*/
private String admin;
/**
* 主题域管理员组织
*/
private String adminOrg;
/**
* 主题域是否公开
*/
private Integer isOpen;
/**
* 主题域可用用户
*/
private String viewer;
/**
* 主题域可用组织
*/
private String viewOrg;
}

View File

@@ -0,0 +1,104 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_metric")
public class MetricDO {
@TableId(type = IdType.AUTO)
private Long id;
/**
* 主体域ID
*/
private Long modelId;
/**
* 指标名称
*/
private String name;
/**
* 字段名称
*/
private String bizName;
/**
* 描述
*/
private String description;
/**
* 指标状态,0正常,1下架,2删除
*/
private Integer status;
/**
* 敏感级别
*/
private Integer sensitiveLevel;
/**
* 指标类型 proxy,expr
*/
private String type;
/**
* 创建时间
*/
private Date createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 更新人
*/
private String updatedBy;
/**
* 数值类型
*/
private String dataFormatType;
/**
* 数值类型参数
*/
private String dataFormat;
/**
*
*/
private String alias;
/**
*
*/
private String tags;
/**
*
*/
private String relateDimensions;
/**
* 类型参数
*/
private String typeParams;
private String ext;
}

View File

@@ -0,0 +1,39 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_metric_query_default_config")
public class MetricQueryDefaultConfigDO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Long metricId;
private String userName;
private String defaultConfig;
private String appKey;
private String appSecret;
private String owner;
private Date createdAt;
private String createdBy;
private Date updatedAt;
private String updatedBy;
}

View File

@@ -0,0 +1,59 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_model")
public class ModelDO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Long domainId;
private String name;
private String bizName;
private String description;
private Long databaseId;
private Integer status;
private Date createdAt;
private String createdBy;
private Date updatedAt;
private String updatedBy;
private String modelDetail;
private String depends;
private String filterSql;
private String viewer;
private String viewOrg;
private String admin;
private String adminOrg;
private Integer isOpen;
private String drillDownDimensions;
private String alias;
private String sourceType;
}

View File

@@ -0,0 +1,26 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("s2_model_rela")
public class ModelRelaDO {
@TableId(type = IdType.AUTO)
private Long id;
private Long domainId;
private Long fromModelId;
private Long toModelId;
private String joinType;
private String joinCondition;
}

View File

@@ -0,0 +1,47 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_view_info")
public class ViewInfoDO {
/**
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
*/
private Long domainId;
/**
* datasource、dimension、metric
*/
private String type;
/**
*/
private Date createdAt;
/**
*/
private String createdBy;
/**
*/
private Date updatedAt;
/**
*/
private String updatedBy;
/**
* config detail
*/
private String config;
}

View File

@@ -0,0 +1,740 @@
package com.tencent.supersonic.headless.server.persistence.dataobject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ViewInfoDOExample {
/**
* s2_view_info
*/
protected String orderByClause;
/**
* s2_view_info
*/
protected boolean distinct;
/**
* s2_view_info
*/
protected List<Criteria> oredCriteria;
/**
* s2_view_info
*/
protected Integer limitStart;
/**
* s2_view_info
*/
protected Integer limitEnd;
/**
* @mbg.generated
*/
public ViewInfoDOExample() {
oredCriteria = new ArrayList<Criteria>();
}
/**
* @mbg.generated
*/
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
/**
* @mbg.generated
*/
public String getOrderByClause() {
return orderByClause;
}
/**
* @mbg.generated
*/
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
/**
* @mbg.generated
*/
public boolean isDistinct() {
return distinct;
}
/**
* @mbg.generated
*/
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
/**
* @mbg.generated
*/
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
/**
* @mbg.generated
*/
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
/**
* @mbg.generated
*/
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
/**
* @mbg.generated
*/
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
/**
* @mbg.generated
*/
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
/**
* @mbg.generated
*/
public void setLimitStart(Integer limitStart) {
this.limitStart = limitStart;
}
/**
* @mbg.generated
*/
public Integer getLimitStart() {
return limitStart;
}
/**
* @mbg.generated
*/
public void setLimitEnd(Integer limitEnd) {
this.limitEnd = limitEnd;
}
/**
* @mbg.generated
*/
public Integer getLimitEnd() {
return limitEnd;
}
/**
* s2_view_info null
*/
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(Long value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(Long value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(Long value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(Long value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(Long value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(Long value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<Long> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<Long> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(Long value1, Long value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(Long value1, Long value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andModelIdIsNull() {
addCriterion("model_id is null");
return (Criteria) this;
}
public Criteria andModelIdIsNotNull() {
addCriterion("model_id is not null");
return (Criteria) this;
}
public Criteria andModelIdEqualTo(Long value) {
addCriterion("model_id =", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdNotEqualTo(Long value) {
addCriterion("model_id <>", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdGreaterThan(Long value) {
addCriterion("model_id >", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdGreaterThanOrEqualTo(Long value) {
addCriterion("model_id >=", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdLessThan(Long value) {
addCriterion("model_id <", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdLessThanOrEqualTo(Long value) {
addCriterion("model_id <=", value, "modelId");
return (Criteria) this;
}
public Criteria andModelIdIn(List<Long> values) {
addCriterion("model_id in", values, "modelId");
return (Criteria) this;
}
public Criteria andModelIdNotIn(List<Long> values) {
addCriterion("model_id not in", values, "modelId");
return (Criteria) this;
}
public Criteria andModelIdBetween(Long value1, Long value2) {
addCriterion("model_id between", value1, value2, "modelId");
return (Criteria) this;
}
public Criteria andModelIdNotBetween(Long value1, Long value2) {
addCriterion("model_id not between", value1, value2, "modelId");
return (Criteria) this;
}
public Criteria andTypeIsNull() {
addCriterion("type is null");
return (Criteria) this;
}
public Criteria andTypeIsNotNull() {
addCriterion("type is not null");
return (Criteria) this;
}
public Criteria andTypeEqualTo(String value) {
addCriterion("type =", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotEqualTo(String value) {
addCriterion("type <>", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThan(String value) {
addCriterion("type >", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThanOrEqualTo(String value) {
addCriterion("type >=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThan(String value) {
addCriterion("type <", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThanOrEqualTo(String value) {
addCriterion("type <=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLike(String value) {
addCriterion("type like", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotLike(String value) {
addCriterion("type not like", value, "type");
return (Criteria) this;
}
public Criteria andTypeIn(List<String> values) {
addCriterion("type in", values, "type");
return (Criteria) this;
}
public Criteria andTypeNotIn(List<String> values) {
addCriterion("type not in", values, "type");
return (Criteria) this;
}
public Criteria andTypeBetween(String value1, String value2) {
addCriterion("type between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andTypeNotBetween(String value1, String value2) {
addCriterion("type not between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andCreatedAtIsNull() {
addCriterion("created_at is null");
return (Criteria) this;
}
public Criteria andCreatedAtIsNotNull() {
addCriterion("created_at is not null");
return (Criteria) this;
}
public Criteria andCreatedAtEqualTo(Date value) {
addCriterion("created_at =", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotEqualTo(Date value) {
addCriterion("created_at <>", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtGreaterThan(Date value) {
addCriterion("created_at >", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtGreaterThanOrEqualTo(Date value) {
addCriterion("created_at >=", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtLessThan(Date value) {
addCriterion("created_at <", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtLessThanOrEqualTo(Date value) {
addCriterion("created_at <=", value, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtIn(List<Date> values) {
addCriterion("created_at in", values, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotIn(List<Date> values) {
addCriterion("created_at not in", values, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtBetween(Date value1, Date value2) {
addCriterion("created_at between", value1, value2, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedAtNotBetween(Date value1, Date value2) {
addCriterion("created_at not between", value1, value2, "createdAt");
return (Criteria) this;
}
public Criteria andCreatedByIsNull() {
addCriterion("created_by is null");
return (Criteria) this;
}
public Criteria andCreatedByIsNotNull() {
addCriterion("created_by is not null");
return (Criteria) this;
}
public Criteria andCreatedByEqualTo(String value) {
addCriterion("created_by =", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotEqualTo(String value) {
addCriterion("created_by <>", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByGreaterThan(String value) {
addCriterion("created_by >", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByGreaterThanOrEqualTo(String value) {
addCriterion("created_by >=", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLessThan(String value) {
addCriterion("created_by <", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLessThanOrEqualTo(String value) {
addCriterion("created_by <=", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByLike(String value) {
addCriterion("created_by like", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotLike(String value) {
addCriterion("created_by not like", value, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByIn(List<String> values) {
addCriterion("created_by in", values, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotIn(List<String> values) {
addCriterion("created_by not in", values, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByBetween(String value1, String value2) {
addCriterion("created_by between", value1, value2, "createdBy");
return (Criteria) this;
}
public Criteria andCreatedByNotBetween(String value1, String value2) {
addCriterion("created_by not between", value1, value2, "createdBy");
return (Criteria) this;
}
public Criteria andUpdatedAtIsNull() {
addCriterion("updated_at is null");
return (Criteria) this;
}
public Criteria andUpdatedAtIsNotNull() {
addCriterion("updated_at is not null");
return (Criteria) this;
}
public Criteria andUpdatedAtEqualTo(Date value) {
addCriterion("updated_at =", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotEqualTo(Date value) {
addCriterion("updated_at <>", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtGreaterThan(Date value) {
addCriterion("updated_at >", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtGreaterThanOrEqualTo(Date value) {
addCriterion("updated_at >=", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtLessThan(Date value) {
addCriterion("updated_at <", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtLessThanOrEqualTo(Date value) {
addCriterion("updated_at <=", value, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtIn(List<Date> values) {
addCriterion("updated_at in", values, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotIn(List<Date> values) {
addCriterion("updated_at not in", values, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtBetween(Date value1, Date value2) {
addCriterion("updated_at between", value1, value2, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedAtNotBetween(Date value1, Date value2) {
addCriterion("updated_at not between", value1, value2, "updatedAt");
return (Criteria) this;
}
public Criteria andUpdatedByIsNull() {
addCriterion("updated_by is null");
return (Criteria) this;
}
public Criteria andUpdatedByIsNotNull() {
addCriterion("updated_by is not null");
return (Criteria) this;
}
public Criteria andUpdatedByEqualTo(String value) {
addCriterion("updated_by =", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotEqualTo(String value) {
addCriterion("updated_by <>", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByGreaterThan(String value) {
addCriterion("updated_by >", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByGreaterThanOrEqualTo(String value) {
addCriterion("updated_by >=", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLessThan(String value) {
addCriterion("updated_by <", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLessThanOrEqualTo(String value) {
addCriterion("updated_by <=", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByLike(String value) {
addCriterion("updated_by like", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotLike(String value) {
addCriterion("updated_by not like", value, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByIn(List<String> values) {
addCriterion("updated_by in", values, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotIn(List<String> values) {
addCriterion("updated_by not in", values, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByBetween(String value1, String value2) {
addCriterion("updated_by between", value1, value2, "updatedBy");
return (Criteria) this;
}
public Criteria andUpdatedByNotBetween(String value1, String value2) {
addCriterion("updated_by not between", value1, value2, "updatedBy");
return (Criteria) this;
}
}
/**
* s2_view_info
*/
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
/**
* s2_view_info null
*/
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
}
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.AppDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AppMapper extends BaseMapper<AppDO> {
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.CollectDO;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 收藏项表 Mapper 接口
* </p>
*
* @author yannsu
* @since 2023-11-09 03:49:33
*/
@Mapper
public interface CollectMapper extends BaseMapper<CollectDO> {
}

View File

@@ -0,0 +1,71 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDOExample;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DatabaseDOMapper {
/**
*
* @mbg.generated
*/
long countByExample(DatabaseDOExample example);
/**
*
* @mbg.generated
*/
int deleteByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int insert(DatabaseDO record);
/**
*
* @mbg.generated
*/
int insertSelective(DatabaseDO record);
/**
*
* @mbg.generated
*/
List<DatabaseDO> selectByExampleWithBLOBs(DatabaseDOExample example);
/**
*
* @mbg.generated
*/
List<DatabaseDO> selectByExample(DatabaseDOExample example);
/**
*
* @mbg.generated
*/
DatabaseDO selectByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(DatabaseDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeyWithBLOBs(DatabaseDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKey(DatabaseDO record);
}

View File

@@ -0,0 +1,16 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.server.persistence.dataobject.DateInfoDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DateInfoMapper {
Boolean upsertDateInfo(DateInfoDO dateInfoDO);
List<DateInfoDO> getDateInfos(ItemDateFilter itemDateFilter);
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import com.tencent.supersonic.headless.server.pojo.DimensionFilter;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DimensionDOCustomMapper {
void batchInsert(List<DimensionDO> dimensionDOS);
void batchUpdate(List<DimensionDO> dimensionDOS);
void batchUpdateStatus(List<DimensionDO> dimensionDOS);
List<DimensionDO> query(DimensionFilter dimensionFilter);
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DimensionDOMapper extends BaseMapper<DimensionDO> {
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DomainDOMapper extends BaseMapper<DomainDO> {
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO;
import com.tencent.supersonic.headless.server.pojo.MetricFilter;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MetricDOCustomMapper {
void batchInsert(List<MetricDO> metricDOS);
void batchUpdate(List<MetricDO> metricDOS);
void batchUpdateStatus(List<MetricDO> metricDOS);
List<MetricDO> query(MetricFilter metricFilter);
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MetricDOMapper extends BaseMapper<MetricDO> {
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricQueryDefaultConfigDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MetricQueryDefaultConfigDOMapper extends BaseMapper<MetricQueryDefaultConfigDO> {
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ModelDOCustomMapper {
void batchUpdateStatus(List<ModelDO> modelDOS);
}

View File

@@ -0,0 +1,11 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ModelDOMapper extends BaseMapper<ModelDO> {
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelRelaDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ModelRelaDOMapper extends BaseMapper<ModelRelaDO> {
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.persistence.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ViewInfoDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ViewInfoDOMapper extends BaseMapper<ViewInfoDO> {
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDO;
import java.util.List;
public interface DatabaseRepository {
void createDatabase(DatabaseDO databaseDO);
void updateDatabase(DatabaseDO databaseDO);
DatabaseDO getDatabase(Long id);
List<DatabaseDO> getDatabaseList();
void deleteDatabase(Long id);
}

View File

@@ -0,0 +1,16 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.request.DateInfoReq;
import com.tencent.supersonic.headless.server.persistence.dataobject.DateInfoDO;
import java.util.List;
public interface DateInfoRepository {
Integer upsertDateInfo(List<DateInfoReq> dateInfoReqs);
List<DateInfoDO> getDateInfos(ItemDateFilter itemDateFilter);
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import com.tencent.supersonic.headless.server.pojo.DimensionFilter;
import java.util.List;
public interface DimensionRepository {
void createDimension(DimensionDO dimensionDO);
void createDimensionBatch(List<DimensionDO> dimensionDOS);
void updateDimension(DimensionDO dimensionDO);
void batchUpdateStatus(List<DimensionDO> dimensionDOS);
DimensionDO getDimensionById(Long id);
List<DimensionDO> getDimension(DimensionFilter dimensionFilter);
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO;
import java.util.List;
public interface DomainRepository {
void createDomain(DomainDO metaDomainDO);
void updateDomain(DomainDO metaDomainDO);
void deleteDomain(Long id);
List<DomainDO> getDomainList();
DomainDO getDomainById(Long id);
}

View File

@@ -0,0 +1,29 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricQueryDefaultConfigDO;
import com.tencent.supersonic.headless.server.pojo.MetricFilter;
import java.util.List;
public interface MetricRepository {
Long createMetric(MetricDO metricDO);
void createMetricBatch(List<MetricDO> metricDOS);
void updateMetric(MetricDO metricDO);
void batchUpdateStatus(List<MetricDO> metricDOS);
MetricDO getMetricById(Long id);
List<MetricDO> getMetric(MetricFilter metricFilter);
void saveDefaultQueryConfig(MetricQueryDefaultConfigDO defaultConfigDO);
void updateDefaultQueryConfig(MetricQueryDefaultConfigDO defaultConfigDO);
MetricQueryDefaultConfigDO getDefaultQueryConfig(Long metricId, String userName);
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import java.util.List;
public interface ModelRepository {
void createModel(ModelDO modelDO);
void updateModel(ModelDO modelDO);
List<ModelDO> getModelList(ModelFilter modelFilter);
ModelDO getModelById(Long id);
void batchUpdate(List<ModelDO> modelDOS);
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.headless.server.persistence.repository;
import com.tencent.supersonic.headless.server.persistence.dataobject.ViewInfoDO;
import java.util.List;
public interface ViewInfoRepository {
List<ViewInfoDO> getViewInfoList(Long domainId);
ViewInfoDO getViewInfoById(Long id);
void deleteViewInfo(Long id);
void createViewInfo(ViewInfoDO viewInfoDO);
void updateViewInfo(ViewInfoDO viewInfoDO);
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDOExample;
import com.tencent.supersonic.headless.server.persistence.mapper.DatabaseDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.DatabaseRepository;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DatabaseRepositoryImpl implements DatabaseRepository {
private DatabaseDOMapper databaseDOMapper;
public DatabaseRepositoryImpl(DatabaseDOMapper databaseDOMapper) {
this.databaseDOMapper = databaseDOMapper;
}
@Override
public void createDatabase(DatabaseDO databaseDO) {
databaseDOMapper.insert(databaseDO);
}
@Override
public void updateDatabase(DatabaseDO databaseDO) {
databaseDOMapper.updateByPrimaryKeyWithBLOBs(databaseDO);
}
@Override
public DatabaseDO getDatabase(Long id) {
return databaseDOMapper.selectByPrimaryKey(id);
}
@Override
public List<DatabaseDO> getDatabaseList() {
return databaseDOMapper.selectByExampleWithBLOBs(new DatabaseDOExample());
}
@Override
public void deleteDatabase(Long id) {
databaseDOMapper.deleteByPrimaryKey(id);
}
}

View File

@@ -0,0 +1,73 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Stopwatch;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.request.DateInfoReq;
import com.tencent.supersonic.headless.server.persistence.dataobject.DateInfoDO;
import com.tencent.supersonic.headless.server.persistence.mapper.DateInfoMapper;
import com.tencent.supersonic.headless.server.persistence.repository.DateInfoRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@Slf4j
@Repository
public class DateInfoRepositoryImpl implements DateInfoRepository {
private ObjectMapper mapper = new ObjectMapper();
@Autowired
private DateInfoMapper dateInfoMapper;
@Override
public Integer upsertDateInfo(List<DateInfoReq> dateInfoCommends) {
List<DateInfoDO> dateInfoDOList = new ArrayList<>();
if (CollectionUtils.isEmpty(dateInfoCommends)) {
log.info("dateInfoCommends size is 0");
return 0;
}
dateInfoCommends.stream().forEach(commend -> {
DateInfoDO dateInfoDO = new DateInfoDO();
BeanUtils.copyProperties(commend, dateInfoDO);
try {
dateInfoDO.setUnavailableDateList(mapper.writeValueAsString(commend.getUnavailableDateList()));
dateInfoDO.setCreatedBy(Constants.ADMIN_LOWER);
dateInfoDO.setUpdatedBy(Constants.ADMIN_LOWER);
} catch (JsonProcessingException e) {
log.info("e,", e);
}
dateInfoDOList.add(dateInfoDO);
});
return batchUpsert(dateInfoDOList);
}
@Override
public List<DateInfoDO> getDateInfos(ItemDateFilter itemDateFilter) {
if (Objects.nonNull(itemDateFilter) && CollectionUtils.isEmpty(itemDateFilter.getItemIds())) {
return new ArrayList<>();
}
return dateInfoMapper.getDateInfos(itemDateFilter);
}
private Integer batchUpsert(List<DateInfoDO> dateInfoDOList) {
Stopwatch stopwatch = Stopwatch.createStarted();
for (DateInfoDO dateInfoDO : dateInfoDOList) {
dateInfoMapper.upsertDateInfo(dateInfoDO);
}
log.info("before final, elapsed time:{}", stopwatch.elapsed(TimeUnit.MILLISECONDS));
return 0;
}
}

View File

@@ -0,0 +1,55 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import com.tencent.supersonic.headless.server.persistence.mapper.DimensionDOCustomMapper;
import com.tencent.supersonic.headless.server.persistence.mapper.DimensionDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.DimensionRepository;
import com.tencent.supersonic.headless.server.pojo.DimensionFilter;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DimensionRepositoryImpl implements DimensionRepository {
private DimensionDOMapper dimensionDOMapper;
private DimensionDOCustomMapper dimensionDOCustomMapper;
public DimensionRepositoryImpl(DimensionDOMapper dimensionDOMapper,
DimensionDOCustomMapper dimensionDOCustomMapper) {
this.dimensionDOMapper = dimensionDOMapper;
this.dimensionDOCustomMapper = dimensionDOCustomMapper;
}
@Override
public void createDimension(DimensionDO dimensionDO) {
dimensionDOMapper.insert(dimensionDO);
}
@Override
public void createDimensionBatch(List<DimensionDO> dimensionDOS) {
dimensionDOCustomMapper.batchInsert(dimensionDOS);
}
@Override
public void updateDimension(DimensionDO dimensionDO) {
dimensionDOMapper.updateById(dimensionDO);
}
@Override
public void batchUpdateStatus(List<DimensionDO> dimensionDOS) {
dimensionDOCustomMapper.batchUpdateStatus(dimensionDOS);
}
@Override
public DimensionDO getDimensionById(Long id) {
return dimensionDOMapper.selectById(id);
}
@Override
public List<DimensionDO> getDimension(DimensionFilter dimensionFilter) {
return dimensionDOCustomMapper.query(dimensionFilter);
}
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO;
import com.tencent.supersonic.headless.server.persistence.mapper.DomainDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.DomainRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
public class DomainRepositoryImpl implements DomainRepository {
private DomainDOMapper domainDOMapper;
public DomainRepositoryImpl(DomainDOMapper domainDOMapper) {
this.domainDOMapper = domainDOMapper;
}
@Override
public void createDomain(DomainDO metaDomainDO) {
domainDOMapper.insert(metaDomainDO);
}
@Override
public void updateDomain(DomainDO metaDomainDO) {
domainDOMapper.updateById(metaDomainDO);
}
@Override
public void deleteDomain(Long id) {
domainDOMapper.deleteById(id);
}
@Override
public List<DomainDO> getDomainList() {
return domainDOMapper.selectList(Wrappers.emptyWrapper());
}
@Override
public DomainDO getDomainById(Long id) {
return domainDOMapper.selectById(id);
}
}

View File

@@ -0,0 +1,83 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricQueryDefaultConfigDO;
import com.tencent.supersonic.headless.server.persistence.mapper.MetricDOCustomMapper;
import com.tencent.supersonic.headless.server.persistence.mapper.MetricDOMapper;
import com.tencent.supersonic.headless.server.persistence.mapper.MetricQueryDefaultConfigDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.MetricRepository;
import com.tencent.supersonic.headless.server.pojo.MetricFilter;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class MetricRepositoryImpl implements MetricRepository {
private MetricDOMapper metricDOMapper;
private MetricDOCustomMapper metricDOCustomMapper;
private MetricQueryDefaultConfigDOMapper metricQueryDefaultConfigDOMapper;
public MetricRepositoryImpl(MetricDOMapper metricDOMapper,
MetricDOCustomMapper metricDOCustomMapper,
MetricQueryDefaultConfigDOMapper metricQueryDefaultConfigDOMapper) {
this.metricDOMapper = metricDOMapper;
this.metricDOCustomMapper = metricDOCustomMapper;
this.metricQueryDefaultConfigDOMapper = metricQueryDefaultConfigDOMapper;
}
@Override
public Long createMetric(MetricDO metricDO) {
metricDOMapper.insert(metricDO);
return metricDO.getId();
}
@Override
public void createMetricBatch(List<MetricDO> metricDOS) {
metricDOCustomMapper.batchInsert(metricDOS);
}
@Override
public void updateMetric(MetricDO metricDO) {
metricDOMapper.updateById(metricDO);
}
@Override
public void batchUpdateStatus(List<MetricDO> metricDOS) {
metricDOCustomMapper.batchUpdateStatus(metricDOS);
}
@Override
public MetricDO getMetricById(Long id) {
return metricDOMapper.selectById(id);
}
@Override
public List<MetricDO> getMetric(MetricFilter metricFilter) {
return metricDOCustomMapper.query(metricFilter);
}
@Override
public void saveDefaultQueryConfig(MetricQueryDefaultConfigDO defaultConfigDO) {
metricQueryDefaultConfigDOMapper.insert(defaultConfigDO);
}
@Override
public void updateDefaultQueryConfig(MetricQueryDefaultConfigDO defaultConfigDO) {
metricQueryDefaultConfigDOMapper.updateById(defaultConfigDO);
}
@Override
public MetricQueryDefaultConfigDO getDefaultQueryConfig(Long metricId, String userName) {
QueryWrapper<MetricQueryDefaultConfigDO> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(MetricQueryDefaultConfigDO::getMetricId, metricId)
.eq(MetricQueryDefaultConfigDO::getCreatedBy, userName);
return metricQueryDefaultConfigDOMapper.selectOne(queryWrapper);
}
}

View File

@@ -0,0 +1,66 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO;
import com.tencent.supersonic.headless.server.persistence.mapper.ModelDOCustomMapper;
import com.tencent.supersonic.headless.server.persistence.mapper.ModelDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.ModelRepository;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Component
public class ModelRepositoryImpl implements ModelRepository {
private ModelDOMapper modelDOMapper;
private ModelDOCustomMapper modelDOCustomMapper;
public ModelRepositoryImpl(ModelDOMapper modelDOMapper,
ModelDOCustomMapper modelDOCustomMapper) {
this.modelDOMapper = modelDOMapper;
this.modelDOCustomMapper = modelDOCustomMapper;
}
@Override
public void createModel(ModelDO datasourceDO) {
modelDOMapper.insert(datasourceDO);
}
@Override
public void updateModel(ModelDO datasourceDO) {
modelDOMapper.updateById(datasourceDO);
}
@Override
public List<ModelDO> getModelList(ModelFilter modelFilter) {
QueryWrapper<ModelDO> wrapper = new QueryWrapper<>();
wrapper.lambda().ne(ModelDO::getStatus, StatusEnum.DELETED.getCode());
if (modelFilter.getDatabaseId() != null) {
wrapper.lambda().eq(ModelDO::getDatabaseId, modelFilter.getDatabaseId());
}
if (!CollectionUtils.isEmpty(modelFilter.getDomainIds())) {
wrapper.lambda().in(ModelDO::getDomainId, modelFilter.getDomainIds());
}
if (!CollectionUtils.isEmpty(modelFilter.getIds())) {
wrapper.lambda().in(ModelDO::getId, modelFilter.getIds());
}
return modelDOMapper.selectList(wrapper);
}
@Override
public ModelDO getModelById(Long id) {
return modelDOMapper.selectById(id);
}
@Override
public void batchUpdate(List<ModelDO> modelDOS) {
modelDOCustomMapper.batchUpdateStatus(modelDOS);
}
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.headless.server.persistence.repository.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ViewInfoDO;
import com.tencent.supersonic.headless.server.persistence.mapper.ViewInfoDOMapper;
import com.tencent.supersonic.headless.server.persistence.repository.ViewInfoRepository;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ViewInfoRepositoryImpl implements ViewInfoRepository {
private ViewInfoDOMapper viewInfoDOMapper;
public ViewInfoRepositoryImpl(ViewInfoDOMapper viewInfoDOMapper) {
this.viewInfoDOMapper = viewInfoDOMapper;
}
@Override
public List<ViewInfoDO> getViewInfoList(Long domainId) {
QueryWrapper<ViewInfoDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ViewInfoDO::getDomainId, domainId);
return viewInfoDOMapper.selectList(wrapper);
}
@Override
public ViewInfoDO getViewInfoById(Long id) {
return viewInfoDOMapper.selectById(id);
}
@Override
public void deleteViewInfo(Long id) {
viewInfoDOMapper.deleteById(id);
}
@Override
public void createViewInfo(ViewInfoDO viewInfoDO) {
viewInfoDOMapper.insert(viewInfoDO);
}
@Override
public void updateViewInfo(ViewInfoDO viewInfoDO) {
viewInfoDOMapper.updateById(viewInfoDO);
}
}

View File

@@ -0,0 +1,18 @@
package com.tencent.supersonic.headless.server.pojo;
import lombok.Data;
@Data
public class ConnectInfo {
private String url;
private String userName;
private String password;
private String database;
}

View File

@@ -0,0 +1,35 @@
package com.tencent.supersonic.headless.server.pojo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.RecordInfo;
import lombok.Data;
import java.util.List;
@Data
public class Database extends RecordInfo {
private Long id;
private Long domainId;
private String name;
private String description;
private String version;
/**
* mysql,clickhouse
*/
private String type;
private ConnectInfo connectInfo;
private List<String> admins = Lists.newArrayList();
private List<String> viewers = Lists.newArrayList();
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.headless.server.pojo;
public enum DatasourceQueryEnum {
SQL_QUERY("sql_query"),
TABLE_QUERY("table_query");
private String name;
DatasourceQueryEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,11 @@
package com.tencent.supersonic.headless.server.pojo;
import lombok.Data;
@Data
public class DimensionFilter extends MetaFilter {
private Integer isTag;
}

View File

@@ -0,0 +1,30 @@
package com.tencent.supersonic.headless.server.pojo;
public enum EngineTypeEnum {
TDW(0, "tdw"),
MYSQL(1, "mysql"),
DORIS(2, "doris"),
CLICKHOUSE(3, "clickhouse"),
KAFKA(4, "kafka"),
H2(5, "h2");
private Integer code;
private String name;
EngineTypeEnum(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,315 @@
package com.tencent.supersonic.headless.server.pojo;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.tencent.supersonic.headless.common.server.enums.DataType;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.server.utils.JdbcDataSourceUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static com.tencent.supersonic.common.pojo.Constants.STATISTIC;
@Slf4j
@Component
public class JdbcDataSource {
private static final Object lockLock = new Object();
private static volatile Map<String, DruidDataSource> dataSourceMap = new ConcurrentHashMap<>();
private static volatile Map<String, Lock> dataSourceLockMap = new ConcurrentHashMap<>();
@Value("${source.lock-time:30}")
@Getter
protected Long lockTime;
@Value("${source.max-active:2}")
@Getter
protected int maxActive;
@Value("${source.initial-size:0}")
@Getter
protected int initialSize;
@Value("${source.min-idle:1}")
@Getter
protected int minIdle;
@Value("${source.max-wait:60000}")
@Getter
protected long maxWait;
@Value("${source.time-between-eviction-runs-millis:2000}")
@Getter
protected long timeBetweenEvictionRunsMillis;
@Value("${source.min-evictable-idle-time-millis:600000}")
@Getter
protected long minEvictableIdleTimeMillis;
@Value("${source.max-evictable-idle-time-millis:900000}")
@Getter
protected long maxEvictableIdleTimeMillis;
@Value("${source.time-between-connect-error-millis:60000}")
@Getter
protected long timeBetweenConnectErrorMillis;
@Value("${source.test-while-idle:true}")
@Getter
protected boolean testWhileIdle;
@Value("${source.test-on-borrow:false}")
@Getter
protected boolean testOnBorrow;
@Value("${source.test-on-return:false}")
@Getter
protected boolean testOnReturn;
@Value("${source.break-after-acquire-failure:true}")
@Getter
protected boolean breakAfterAcquireFailure;
@Value("${source.connection-error-retry-attempts:1}")
@Getter
protected int connectionErrorRetryAttempts;
@Value("${source.keep-alive:false}")
@Getter
protected boolean keepAlive;
@Value("${source.validation-query-timeout:5}")
@Getter
protected int validationQueryTimeout;
@Value("${source.validation-query:'select 1'}")
@Getter
protected String validationQuery;
@Value("${source.filters:'stat'}")
@Getter
protected String filters;
@Autowired
WallFilter wallFilter;
@Bean(name = "wallConfig")
WallConfig wallConfig() {
WallConfig config = new WallConfig();
config.setDeleteAllow(false);
config.setUpdateAllow(false);
config.setInsertAllow(false);
config.setReplaceAllow(false);
config.setMergeAllow(false);
config.setTruncateAllow(false);
config.setCreateTableAllow(false);
config.setAlterTableAllow(false);
config.setDropTableAllow(false);
config.setCommentAllow(true);
config.setUseAllow(false);
config.setDescribeAllow(false);
config.setShowAllow(false);
config.setSelectWhereAlwayTrueCheck(false);
config.setSelectHavingAlwayTrueCheck(false);
config.setSelectUnionCheck(false);
config.setConditionDoubleConstAllow(true);
config.setConditionAndAlwayTrueAllow(true);
config.setConditionAndAlwayFalseAllow(true);
return config;
}
@Bean(name = "wallFilter")
@DependsOn("wallConfig")
WallFilter wallFilter(WallConfig wallConfig) {
WallFilter wfilter = new WallFilter();
wfilter.setConfig(wallConfig);
return wfilter;
}
private Lock getDataSourceLock(String key) {
if (dataSourceLockMap.containsKey(key)) {
return dataSourceLockMap.get(key);
}
synchronized (lockLock) {
if (dataSourceLockMap.containsKey(key)) {
return dataSourceLockMap.get(key);
}
Lock lock = new ReentrantLock();
dataSourceLockMap.put(key, lock);
return lock;
}
}
public void removeDatasource(DatabaseResp jdbcSourceInfo) {
String key = getDataSourceKey(jdbcSourceInfo);
Lock lock = getDataSourceLock(key);
if (!lock.tryLock()) {
return;
}
try {
DruidDataSource druidDataSource = dataSourceMap.remove(key);
if (druidDataSource != null) {
druidDataSource.close();
}
dataSourceLockMap.remove(key);
} finally {
lock.unlock();
}
}
public DruidDataSource getDataSource(DatabaseResp jdbcSourceInfo) throws RuntimeException {
String name = jdbcSourceInfo.getName();
String type = jdbcSourceInfo.getType();
String jdbcUrl = jdbcSourceInfo.getUrl();
String username = jdbcSourceInfo.getUsername();
String password = jdbcSourceInfo.getPassword();
String key = getDataSourceKey(jdbcSourceInfo);
DruidDataSource druidDataSource = dataSourceMap.get(key);
if (druidDataSource != null && !druidDataSource.isClosed()) {
return druidDataSource;
}
Lock lock = getDataSourceLock(key);
try {
if (!lock.tryLock(lockTime, TimeUnit.SECONDS)) {
druidDataSource = dataSourceMap.get(key);
if (druidDataSource != null && !druidDataSource.isClosed()) {
return druidDataSource;
}
throw new RuntimeException("Unable to get datasource for jdbcUrl: " + jdbcUrl);
}
} catch (InterruptedException e) {
throw new RuntimeException("Unable to get datasource for jdbcUrl: " + jdbcUrl);
}
druidDataSource = dataSourceMap.get(key);
if (druidDataSource != null && !druidDataSource.isClosed()) {
lock.unlock();
return druidDataSource;
}
druidDataSource = new DruidDataSource();
try {
String className = JdbcDataSourceUtils.getDriverClassName(jdbcUrl);
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to get driver instance for jdbcUrl: " + jdbcUrl);
}
druidDataSource.setDriverClassName(className);
druidDataSource.setName(name);
druidDataSource.setUrl(jdbcUrl);
druidDataSource.setUsername(username);
if (!jdbcUrl.toLowerCase().contains(DataType.PRESTO.getFeature())) {
druidDataSource.setPassword(password);
}
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
druidDataSource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
druidDataSource.setTimeBetweenConnectErrorMillis(timeBetweenConnectErrorMillis);
druidDataSource.setTestWhileIdle(testWhileIdle);
druidDataSource.setTestOnBorrow(testOnBorrow);
druidDataSource.setTestOnReturn(testOnReturn);
druidDataSource.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
druidDataSource.setBreakAfterAcquireFailure(breakAfterAcquireFailure);
druidDataSource.setKeepAlive(keepAlive);
druidDataSource.setValidationQueryTimeout(validationQueryTimeout);
druidDataSource.setRemoveAbandoned(true);
druidDataSource.setRemoveAbandonedTimeout(3600 + 5 * 60);
druidDataSource.setLogAbandoned(true);
// default validation query
String driverName = druidDataSource.getDriverClassName();
if (driverName.indexOf("sqlserver") != -1 || driverName.indexOf("mysql") != -1
|| driverName.indexOf("h2") != -1 || driverName.indexOf("moonbox") != -1) {
druidDataSource.setValidationQuery("select 1");
}
if (driverName.indexOf("oracle") != -1) {
druidDataSource.setValidationQuery("select 1 from dual");
}
if (driverName.indexOf("elasticsearch") != -1) {
druidDataSource.setValidationQuery(null);
}
// druid wall filter not support some database so set type mysql
if (DataType.MOONBOX == DataType.urlOf(jdbcUrl)
|| DataType.MONGODB == DataType.urlOf(jdbcUrl)
|| DataType.ELASTICSEARCH == DataType.urlOf(jdbcUrl)
|| DataType.CASSANDRA == DataType.urlOf(jdbcUrl)
|| DataType.VERTICA == DataType.urlOf(jdbcUrl)
|| DataType.KYLIN == DataType.urlOf(jdbcUrl)
|| DataType.HANA == DataType.urlOf(jdbcUrl)
|| DataType.IMPALA == DataType.urlOf(jdbcUrl)
|| DataType.TDENGINE == DataType.urlOf(jdbcUrl)) {
wallFilter.setDbType(DataType.MYSQL.getFeature());
}
Properties properties = new Properties();
if (driverName.indexOf("mysql") != -1) {
properties.setProperty("druid.mysql.usePingMethod", "false");
}
druidDataSource.setConnectProperties(properties);
try {
// statistic and ck source don't need wall filter
if (!STATISTIC.equals(name) && !DataType.CLICKHOUSE.getFeature().equalsIgnoreCase(type)) {
druidDataSource.setProxyFilters(Arrays.asList(new Filter[]{wallFilter}));
}
druidDataSource.setFilters(filters);
druidDataSource.init();
} catch (Exception e) {
log.error("Exception during pool initialization", e);
throw new RuntimeException(e.getMessage());
}
dataSourceMap.put(key, druidDataSource);
} finally {
lock.unlock();
}
return druidDataSource;
}
private String getDataSourceKey(DatabaseResp jdbcSourceInfo) {
return JdbcDataSourceUtils.getKey(jdbcSourceInfo.getName(),
jdbcSourceInfo.getUrl(),
jdbcSourceInfo.getUsername(),
jdbcSourceInfo.getPassword(), "", false);
}
}

View File

@@ -0,0 +1,33 @@
package com.tencent.supersonic.headless.server.pojo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
public class MetaFilter {
private String id;
private String name;
private String bizName;
private String createdBy;
private List<Long> modelIds;
private Integer sensitiveLevel;
private Integer status;
private String key;
private List<Long> ids;
public MetaFilter(List<Long> modelIds) {
this.modelIds = modelIds;
}
}

View File

@@ -0,0 +1,10 @@
package com.tencent.supersonic.headless.server.pojo;
import lombok.Data;
@Data
public class MetricFilter extends MetaFilter {
private String type;
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.headless.server.pojo;
import lombok.Data;
import java.util.List;
@Data
public class ModelFilter extends MetaFilter {
private Long databaseId;
private List<Long> domainIds;
}

View File

@@ -0,0 +1,30 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import com.tencent.supersonic.headless.common.server.enums.ModelSourceType;
import lombok.Data;
import java.util.List;
@Data
public class DataModelYamlTpl {
private String name;
private Long sourceId;
private String sqlQuery;
private String tableQuery;
private List<IdentifyYamlTpl> identifiers;
private List<DimensionYamlTpl> dimensions;
private List<MeasureYamlTpl> measures;
private ModelSourceType modelSourceTypeEnum;
}

View File

@@ -0,0 +1,13 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import lombok.Data;
@Data
public class DimensionTimeTypeParamsTpl {
private String isPrimary;
private String timeGranularity;
}

View File

@@ -0,0 +1,22 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import com.tencent.supersonic.common.pojo.enums.DataTypeEnums;
import lombok.Data;
@Data
public class DimensionYamlTpl {
private String name;
private String owners;
private String type;
private String expr;
private DimensionTimeTypeParamsTpl typeParams;
private DataTypeEnums dataType;
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class IdentifyYamlTpl {
private String name;
/**
* 主键 primary 外键 foreign
*/
private String type;
}

View File

@@ -0,0 +1,25 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MeasureYamlTpl {
private String name;
private String agg;
private String expr;
private String constraint;
private String alias;
private String createMetric;
}

View File

@@ -0,0 +1,15 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import lombok.Data;
import java.util.List;
@Data
public class MetricTypeParamsYamlTpl {
private List<MeasureYamlTpl> measures;
private String expr;
}

View File

@@ -0,0 +1,21 @@
package com.tencent.supersonic.headless.server.pojo.yaml;
import lombok.Data;
import java.util.List;
@Data
public class MetricYamlTpl {
private String name;
private List<String> owners;
private String type;
private MetricTypeParamsYamlTpl typeParams;
}

View File

@@ -0,0 +1,84 @@
package com.tencent.supersonic.headless.server.rest;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.headless.common.server.request.AppQueryReq;
import com.tencent.supersonic.headless.common.server.request.AppReq;
import com.tencent.supersonic.headless.common.server.response.AppDetailResp;
import com.tencent.supersonic.headless.common.server.response.AppResp;
import com.tencent.supersonic.headless.server.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/api/semantic/app")
public class AppController {
@Autowired
private AppService appService;
@PostMapping
public boolean save(@RequestBody AppReq app,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
appService.save(app, user);
return true;
}
@PutMapping
public boolean update(@RequestBody AppReq app,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
appService.update(app, user);
return true;
}
@PutMapping("/online/{id}")
public boolean online(@PathVariable("id") Integer id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
appService.online(id, user);
return true;
}
@PutMapping("/offline/{id}")
public boolean offline(@PathVariable("id") Integer id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
appService.offline(id, user);
return true;
}
@DeleteMapping("/{id}")
public boolean delete(@PathVariable("id") Integer id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
appService.delete(id, user);
return true;
}
@GetMapping("/{id}")
public AppDetailResp getApp(@PathVariable("id") Integer id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return appService.getApp(id, user);
}
@PostMapping("/page")
public PageInfo<AppResp> pageApp(@RequestBody AppQueryReq appQueryReq,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return appService.pageApp(appQueryReq, user);
}
}

View File

@@ -0,0 +1,47 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.headless.server.persistence.dataobject.CollectDO;
import com.tencent.supersonic.headless.server.service.CollectService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/***
* 创建收藏指标的逻辑
*/
@RestController
@RequestMapping("/api/semantic/collect")
public class CollectController {
private CollectService collectService;
public CollectController(CollectService collectService) {
this.collectService = collectService;
}
@PostMapping("/createCollectionIndicators")
public boolean createCollectionIndicators(@RequestBody CollectDO collectDO,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return collectService.createCollectionIndicators(user, collectDO.getId());
}
@DeleteMapping("/deleteCollectionIndicators/{id}")
public boolean deleteCollectionIndicators(@PathVariable Long id,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return collectService.deleteCollectionIndicators(user, id);
}
}

View File

@@ -0,0 +1,93 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.headless.common.server.request.DatabaseReq;
import com.tencent.supersonic.headless.common.server.request.SqlExecuteReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.headless.server.service.DatabaseService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/database")
public class DatabaseController {
private DatabaseService databaseService;
public DatabaseController(DatabaseService databaseService) {
this.databaseService = databaseService;
}
@PostMapping("/testConnect")
public boolean testConnect(@RequestBody DatabaseReq databaseReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return databaseService.testConnect(databaseReq, user);
}
@PostMapping("/createOrUpdateDatabase")
public DatabaseResp createOrUpdateDatabase(@RequestBody DatabaseReq databaseReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return databaseService.createOrUpdateDatabase(databaseReq, user);
}
@GetMapping("/{id}")
public DatabaseResp getDatabase(@PathVariable("id") Long id) {
return databaseService.getDatabase(id);
}
@GetMapping("/getDatabaseList")
public List<DatabaseResp> getDatabaseList(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return databaseService.getDatabaseList(user);
}
@DeleteMapping("/{id}")
public boolean deleteDatabase(@PathVariable("id") Long id) {
databaseService.deleteDatabase(id);
return true;
}
@PostMapping("/executeSql")
public QueryResultWithSchemaResp executeSql(@RequestBody SqlExecuteReq sqlExecuteReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return databaseService.executeSql(sqlExecuteReq.getSql(), sqlExecuteReq.getId(), user);
}
@RequestMapping("/getDbNames/{id}")
public QueryResultWithSchemaResp getDbNames(@PathVariable("id") Long id) {
return databaseService.getDbNames(id);
}
@RequestMapping("/getTables/{id}/{db}")
public QueryResultWithSchemaResp getTables(@PathVariable("id") Long id,
@PathVariable("db") String db) {
return databaseService.getTables(id, db);
}
@RequestMapping("/getColumns/{id}/{db}/{table}")
public QueryResultWithSchemaResp getColumns(@PathVariable("id") Long id,
@PathVariable("db") String db,
@PathVariable("table") String table) {
return databaseService.getColumns(id, db, table);
}
}

View File

@@ -0,0 +1,127 @@
package com.tencent.supersonic.headless.server.rest;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
import com.tencent.supersonic.headless.common.server.pojo.DimValueMap;
import com.tencent.supersonic.headless.common.server.request.DimensionReq;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.PageDimensionReq;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.server.pojo.DimensionFilter;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.DimensionService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/dimension")
public class DimensionController {
private DimensionService dimensionService;
public DimensionController(DimensionService dimensionService) {
this.dimensionService = dimensionService;
}
/**
* 创建维度
*
* @param dimensionReq
*/
@PostMapping("/createDimension")
public Boolean createDimension(@RequestBody DimensionReq dimensionReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
dimensionService.createDimension(dimensionReq, user);
return true;
}
@PostMapping("/updateDimension")
public Boolean updateDimension(@RequestBody DimensionReq dimensionReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
dimensionService.updateDimension(dimensionReq, user);
return true;
}
@PostMapping("/batchUpdateStatus")
public Boolean batchUpdateStatus(@RequestBody MetaBatchReq metaBatchReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
dimensionService.batchUpdateStatus(metaBatchReq, user);
return true;
}
@PostMapping("/mockDimensionAlias")
public List<String> mockMetricAlias(@RequestBody DimensionReq dimensionReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return dimensionService.mockAlias(dimensionReq, "dimension", user);
}
@PostMapping("/mockDimensionValuesAlias")
public List<DimValueMap> mockDimensionValuesAlias(@RequestBody DimensionReq dimensionReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return dimensionService.mockDimensionValueAlias(dimensionReq, user);
}
@GetMapping("/getDimensionList/{modelId}")
public List<DimensionResp> getDimension(@PathVariable("modelId") Long modelId) {
DimensionFilter dimensionFilter = new DimensionFilter();
dimensionFilter.setModelIds(Lists.newArrayList(modelId));
return dimensionService.getDimensions(dimensionFilter);
}
@GetMapping("/getDimensionInModelCluster/{modelId}")
public List<DimensionResp> getDimensionInModelCluster(@PathVariable("modelId") Long modelId) {
return dimensionService.getDimensionInModelCluster(modelId);
}
@GetMapping("/{modelId}/{dimensionName}")
public DimensionResp getDimensionDescByNameAndId(@PathVariable("modelId") Long modelId,
@PathVariable("dimensionName") String dimensionBizName) {
return dimensionService.getDimension(dimensionBizName, modelId);
}
@PostMapping("/queryDimension")
public PageInfo<DimensionResp> queryDimension(@RequestBody PageDimensionReq pageDimensionReq) {
return dimensionService.queryDimension(pageDimensionReq);
}
@DeleteMapping("deleteDimension/{id}")
public Boolean deleteDimension(@PathVariable("id") Long id,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
dimensionService.deleteDimension(id, user);
return true;
}
@GetMapping("/getAllHighSensitiveDimension")
public List<DimensionResp> getAllHighSensitiveDimension() {
MetaFilter metaFilter = new MetaFilter();
metaFilter.setSensitiveLevel(SensitiveLevelEnum.HIGH.getCode());
return dimensionService.getDimensions(metaFilter);
}
}

View File

@@ -0,0 +1,76 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.headless.common.server.request.DomainReq;
import com.tencent.supersonic.headless.common.server.request.DomainUpdateReq;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import com.tencent.supersonic.headless.server.service.DomainService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/semantic/domain")
public class DomainController {
private DomainService domainService;
public DomainController(DomainService domainService) {
this.domainService = domainService;
}
@PostMapping("/createDomain")
public Boolean createDomain(@RequestBody DomainReq domainReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
domainService.createDomain(domainReq, user);
return true;
}
@PostMapping("/updateDomain")
public Boolean updateDomain(@RequestBody DomainUpdateReq domainUpdateReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
domainService.updateDomain(domainUpdateReq, user);
return true;
}
@DeleteMapping("/deleteDomain/{domainId}")
public Boolean deleteDomain(@PathVariable("domainId") Long domainId) {
domainService.deleteDomain(domainId);
return true;
}
@GetMapping("/getDomainList")
public List<DomainResp> getDomainList(HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return domainService.getDomainListWithAdminAuth(user);
}
@GetMapping("/getDomain/{id}")
public DomainResp getDomain(@PathVariable("id") Long id) {
return domainService.getDomain(id);
}
@GetMapping("/getDomainListByIds/{domainIds}")
public List<DomainResp> getDomainListByIds(@PathVariable("domainIds") String domainIds) {
return domainService.getDomainList(Arrays.stream(domainIds.split(",")).map(Long::parseLong)
.collect(Collectors.toList()));
}
}

View File

@@ -0,0 +1,149 @@
package com.tencent.supersonic.headless.server.rest;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
import com.tencent.supersonic.headless.common.server.pojo.DrillDownDimension;
import com.tencent.supersonic.headless.common.server.pojo.MetricQueryDefaultConfig;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.MetricReq;
import com.tencent.supersonic.headless.common.server.request.PageMetricReq;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.pojo.MetricFilter;
import com.tencent.supersonic.headless.server.service.MetricService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;
@RestController
@RequestMapping("/api/semantic/metric")
public class MetricController {
private MetricService metricService;
public MetricController(MetricService metricService) {
this.metricService = metricService;
}
@PostMapping("/creatExprMetric")
public Boolean creatExprMetric(@RequestBody MetricReq metricReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
metricService.createMetric(metricReq, user);
return true;
}
@PostMapping("/updateExprMetric")
public Boolean updateExprMetric(@RequestBody MetricReq metricReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
metricService.updateExprMetric(metricReq, user);
return true;
}
@PostMapping("/batchUpdateStatus")
public Boolean batchUpdateStatus(@RequestBody MetaBatchReq metaBatchReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
metricService.batchUpdateStatus(metaBatchReq, user);
return true;
}
@PostMapping("/mockMetricAlias")
public List<String> mockMetricAlias(@RequestBody MetricReq metricReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return metricService.mockAlias(metricReq, "indicator", user);
}
@GetMapping("/getMetricList/{modelId}")
public List<MetricResp> getMetricList(@PathVariable("modelId") Long modelId) {
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(modelId));
return metricService.getMetrics(metaFilter);
}
@PostMapping("/queryMetric")
public PageInfo<MetricResp> queryMetric(@RequestBody PageMetricReq pageMetricReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return metricService.queryMetric(pageMetricReq, user);
}
@Deprecated
@GetMapping("getMetric/{modelId}/{bizName}")
public MetricResp getMetric(@PathVariable("modelId") Long modelId, @PathVariable("bizName") String bizName) {
return metricService.getMetric(modelId, bizName);
}
@GetMapping("getMetric/{id}")
public MetricResp getMetric(@PathVariable("id") Long id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return metricService.getMetric(id, user);
}
@DeleteMapping("deleteMetric/{id}")
public Boolean deleteMetric(@PathVariable("id") Long id,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
metricService.deleteMetric(id, user);
return true;
}
@GetMapping("/getAllHighSensitiveMetric")
public List<MetricResp> getAllHighSensitiveMetric() {
MetricFilter metricFilter = new MetricFilter();
metricFilter.setSensitiveLevel(SensitiveLevelEnum.HIGH.getCode());
return metricService.getMetrics(metricFilter);
}
@GetMapping("/getMetricTags")
public Set<String> getMetricTags() {
return metricService.getMetricTags();
}
@GetMapping("/getDrillDownDimension")
public List<DrillDownDimension> getDrillDownDimension(Long metricId) {
return metricService.getDrillDownDimension(metricId);
}
@PostMapping("/saveMetricQueryDefaultConfig")
public boolean saveMetricQueryDefaultConfig(@RequestBody MetricQueryDefaultConfig queryDefaultConfig,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
metricService.saveMetricQueryDefaultConfig(queryDefaultConfig, user);
return true;
}
@RequestMapping("getMetricQueryDefaultConfig/{metricId}")
public MetricQueryDefaultConfig getMetricQueryDefaultConfig(@PathVariable("metricId") Long metricId,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return metricService.getMetricQueryDefaultConfig(metricId, user);
}
}

View File

@@ -0,0 +1,95 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.ModelReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import com.tencent.supersonic.headless.server.service.ModelService;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/api/semantic/model")
public class ModelController {
private ModelService modelService;
public ModelController(ModelService modelService) {
this.modelService = modelService;
}
@PostMapping("/createModel")
public Boolean createModel(@RequestBody ModelReq modelReq,
HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
modelService.createModel(modelReq, user);
return true;
}
@PostMapping("/updateModel")
public Boolean updateModel(@RequestBody ModelReq modelReq,
HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
modelService.updateModel(modelReq, user);
return true;
}
@DeleteMapping("/deleteModel/{modelId}")
public Boolean deleteModel(@PathVariable("modelId") Long modelId,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
modelService.deleteModel(modelId, user);
return true;
}
@GetMapping("/getModelList/{domainId}")
public List<ModelResp> getModelList(@PathVariable("domainId") Long domainId,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return modelService.getModelListWithAuth(user, domainId, AuthType.ADMIN);
}
@GetMapping("/getModel/{id}")
public ModelResp getModel(@PathVariable("id") Long id) {
return modelService.getModel(id);
}
@GetMapping("/getModelListByIds/{modelIds}")
public List<ModelResp> getModelListByIds(@PathVariable("modelIds") String modelIds) {
List<Long> ids = Arrays.stream(modelIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(ids);
return modelService.getModelList(modelFilter);
}
@GetMapping("/getModelDatabase/{modelId}")
public DatabaseResp getModelDatabase(@PathVariable("modelId") Long modelId) {
return modelService.getDatabaseByModelId(modelId);
}
@PostMapping("/batchUpdateStatus")
public Boolean batchUpdateStatus(@RequestBody MetaBatchReq metaBatchReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
modelService.batchUpdateStatus(metaBatchReq, user);
return true;
}
}

View File

@@ -0,0 +1,48 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.headless.server.service.ModelRelaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/modelRela")
public class ModelRelaController {
@Autowired
private ModelRelaService modelRelaService;
@PostMapping
public boolean save(@RequestBody ModelRela modelRela, User user) {
modelRelaService.save(modelRela, user);
return true;
}
@PutMapping
public boolean update(@RequestBody ModelRela modelRela, User user) {
modelRelaService.update(modelRela, user);
return true;
}
@RequestMapping("/list")
public List<ModelRela> getModelRelaList(@RequestParam("domainId") Long domainId) {
return modelRelaService.getModelRelaList(domainId);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") Long id) {
modelRelaService.delete(id);
}
}

View File

@@ -0,0 +1,57 @@
package com.tencent.supersonic.headless.server.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.headless.common.server.request.ViewInfoReq;
import com.tencent.supersonic.headless.common.server.response.ModelSchemaRelaResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.ViewInfoDO;
import com.tencent.supersonic.headless.server.service.impl.ViewInfoServiceImpl;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/viewInfo")
public class ViewInfoController {
private ViewInfoServiceImpl viewInfoServiceImpl;
public ViewInfoController(ViewInfoServiceImpl viewInfoServiceImpl) {
this.viewInfoServiceImpl = viewInfoServiceImpl;
}
@PostMapping("/createOrUpdateViewInfo")
public ViewInfoDO createOrUpdateViewInfo(@RequestBody ViewInfoReq viewInfoReq, HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return viewInfoServiceImpl.createOrUpdateViewInfo(viewInfoReq, user);
}
@GetMapping("/getViewInfoList/{domainId}")
public List<ViewInfoDO> getViewInfoList(@PathVariable("domainId") Long domainId) {
return viewInfoServiceImpl.getViewInfoList(domainId);
}
@DeleteMapping("/deleteViewInfo/{id}")
public void deleteViewInfo(@PathVariable("id") Long id) {
viewInfoServiceImpl.deleteViewInfo(id);
}
@GetMapping("/getDomainSchemaRela/{domainId}")
public List<ModelSchemaRelaResp> getDomainSchema(@PathVariable("domainId") Long domainId,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return viewInfoServiceImpl.getDomainSchema(domainId, user);
}
}

View File

@@ -0,0 +1,28 @@
package com.tencent.supersonic.headless.server.service;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.common.server.request.AppQueryReq;
import com.tencent.supersonic.headless.common.server.request.AppReq;
import com.tencent.supersonic.headless.common.server.response.AppDetailResp;
import com.tencent.supersonic.headless.common.server.response.AppResp;
public interface AppService {
AppDetailResp save(AppReq app, User user);
AppDetailResp update(AppReq app, User user);
void online(Integer id, User user);
void offline(Integer id, User user);
void delete(Integer id, User user);
PageInfo<AppResp> pageApp(AppQueryReq appQueryReq, User user);
AppDetailResp getApp(Integer id, User user);
AppDetailResp getApp(Integer id);
}

View File

@@ -0,0 +1,47 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DataModelYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.MetricYamlTpl;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface Catalog {
DatabaseResp getDatabase(Long id);
DatabaseResp getDatabaseByModelId(Long modelId);
String getModelFullPath(List<Long> modelIds);
DimensionResp getDimension(String bizName, Long modelId);
DimensionResp getDimension(Long id);
List<DimensionResp> getDimensions(MetaFilter metaFilter);
List<MetricResp> getMetrics(MetaFilter metaFilter);
MetricResp getMetric(Long id);
List<ModelRela> getModelRela(List<Long> modelIds);
void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName);
ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric);
List<ModelResp> getModelList(List<Long> modelIds);
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.server.persistence.dataobject.CollectDO;
import java.util.List;
/**
* @author yannsu
*/
public interface CollectService {
Boolean createCollectionIndicators(User user, Long id);
Boolean deleteCollectionIndicators(User user, Long id);
List<CollectDO> getCollectList(String username);
}

View File

@@ -0,0 +1,32 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.common.server.request.DatabaseReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.QueryResultWithSchemaResp;
import java.util.List;
public interface DatabaseService {
QueryResultWithSchemaResp executeSql(String sql, DatabaseResp databaseResp);
QueryResultWithSchemaResp executeSql(String sql, Long id, User user);
boolean testConnect(DatabaseReq databaseReq, User user);
DatabaseResp createOrUpdateDatabase(DatabaseReq databaseReq, User user);
List<DatabaseResp> getDatabaseList(User user);
void deleteDatabase(Long databaseId);
DatabaseResp getDatabase(Long id);
QueryResultWithSchemaResp getDbNames(Long id);
QueryResultWithSchemaResp getTables(Long id, String db);
QueryResultWithSchemaResp getColumns(Long id, String db, String table);
}

View File

@@ -0,0 +1,42 @@
package com.tencent.supersonic.headless.server.service;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.headless.common.server.pojo.DimValueMap;
import com.tencent.supersonic.headless.common.server.request.DimensionReq;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.PageDimensionReq;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import java.util.List;
public interface DimensionService {
List<DimensionResp> getDimensions(MetaFilter metaFilter);
DimensionResp getDimension(String bizName, Long modelId);
DimensionResp getDimension(Long id);
void batchUpdateStatus(MetaBatchReq metaBatchReq, User user);
void createDimension(DimensionReq dimensionReq, User user) throws Exception;
void createDimensionBatch(List<DimensionReq> dimensionReqs, User user) throws Exception;
void updateDimension(DimensionReq dimensionReq, User user) throws Exception;
PageInfo<DimensionResp> queryDimension(PageDimensionReq pageDimensionReq);
void deleteDimension(Long id, User user);
List<DimensionResp> getDimensionInModelCluster(Long modelId);
List<String> mockAlias(DimensionReq dimensionReq, String mockType, User user);
List<DimValueMap> mockDimensionValueAlias(DimensionReq dimensionReq, User user);
void sendDimensionEventBatch(List<Long> modelIds, EventType eventType);
}

View File

@@ -0,0 +1,37 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.headless.common.server.request.DomainReq;
import com.tencent.supersonic.headless.common.server.request.DomainUpdateReq;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface DomainService {
DomainResp getDomain(Long id);
Map<Long, String> getDomainFullPath();
void createDomain(DomainReq domainReq, User user);
void updateDomain(DomainUpdateReq domainUpdateReq, User user);
void deleteDomain(Long id);
List<DomainResp> getDomainList();
List<DomainResp> getDomainList(List<Long> domainIds);
Map<Long, DomainResp> getDomainMap();
List<DomainResp> getDomainListWithAdminAuth(User user);
Set<DomainResp> getDomainAuthSet(User user, AuthType authTypeEnum);
Set<DomainResp> getDomainChildren(List<Long> domainId);
}

View File

@@ -0,0 +1,53 @@
package com.tencent.supersonic.headless.server.service;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.DataItem;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.headless.common.server.pojo.DrillDownDimension;
import com.tencent.supersonic.headless.common.server.pojo.MetricQueryDefaultConfig;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.MetricReq;
import com.tencent.supersonic.headless.common.server.request.PageMetricReq;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import java.util.List;
import java.util.Set;
public interface MetricService {
void createMetric(MetricReq metricReq, User user) throws Exception;
void createMetricBatch(List<MetricReq> metricReqs, User user) throws Exception;
void updateExprMetric(MetricReq metricReq, User user) throws Exception;
void batchUpdateStatus(MetaBatchReq metaBatchReq, User user);
void deleteMetric(Long id, User user) throws Exception;
PageInfo<MetricResp> queryMetric(PageMetricReq pageMetricReq, User user);
List<MetricResp> getMetrics(MetaFilter metaFilter);
MetricResp getMetric(Long modelId, String bizName);
MetricResp getMetric(Long id, User user);
MetricResp getMetric(Long id);
List<String> mockAlias(MetricReq metricReq, String mockType, User user);
Set<String> getMetricTags();
List<DrillDownDimension> getDrillDownDimension(Long metricId);
List<DataItem> getDataItems(Long modelId);
void saveMetricQueryDefaultConfig(MetricQueryDefaultConfig defaultConfig, User user);
MetricQueryDefaultConfig getMetricQueryDefaultConfig(Long metricId, User user);
void sendMetricEventBatch(List<Long> modelIds, EventType eventType);
}

View File

@@ -0,0 +1,19 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ModelRela;
import java.util.List;
public interface ModelRelaService {
void save(ModelRela modelRela, User user);
void update(ModelRela modelRela, User user);
List<ModelRela> getModelRelaList(Long domainId);
List<ModelRela> getModelRela(List<Long> modelIds);
void delete(Long id);
}

View File

@@ -0,0 +1,61 @@
package com.tencent.supersonic.headless.server.service;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.ModelReq;
import com.tencent.supersonic.headless.common.server.request.ModelSchemaFilterReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.MeasureResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.common.server.response.ModelSchemaResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DataModelYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.MetricYamlTpl;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ModelService {
ModelResp createModel(ModelReq datasourceReq, User user) throws Exception;
ModelResp updateModel(ModelReq datasourceReq, User user) throws Exception;
List<ModelResp> getModelList(ModelFilter modelFilter);
Map<Long, ModelResp> getModelMap();
void deleteModel(Long id, User user);
ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric);
List<MeasureResp> getMeasureListOfModel(List<Long> modelIds);
List<ModelResp> getModelListWithAuth(User user, Long domainId, AuthType authType);
List<ModelResp> getModelAuthList(User user, AuthType authTypeEnum);
List<ModelResp> getModelByDomainIds(List<Long> domainIds);
ModelResp getModel(Long id);
List<String> getModelAdmin(Long id);
ModelSchemaResp fetchSingleModelSchema(Long modelId);
List<ModelSchemaResp> fetchModelSchema(ModelSchemaFilterReq modelSchemaFilterReq);
DatabaseResp getDatabaseByModelId(Long modelId);
void batchUpdateStatus(MetaBatchReq metaBatchReq, User user);
void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName);
}

View File

@@ -0,0 +1,225 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.pojo.exception.InvalidPermissionException;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.PageUtils;
import com.tencent.supersonic.headless.common.server.enums.AppStatus;
import com.tencent.supersonic.headless.common.server.pojo.AppConfig;
import com.tencent.supersonic.headless.common.server.request.AppQueryReq;
import com.tencent.supersonic.headless.common.server.request.AppReq;
import com.tencent.supersonic.headless.common.server.response.AppDetailResp;
import com.tencent.supersonic.headless.common.server.response.AppResp;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.AppDO;
import com.tencent.supersonic.headless.server.persistence.mapper.AppMapper;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.AppService;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.MetricService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
public class AppServiceImpl extends ServiceImpl<AppMapper, AppDO> implements AppService {
private AppMapper appMapper;
private MetricService metricService;
private DimensionService dimensionService;
public AppServiceImpl(AppMapper appMapper, MetricService metricService,
DimensionService dimensionService) {
this.appMapper = appMapper;
this.metricService = metricService;
this.dimensionService = dimensionService;
}
@Override
public AppDetailResp save(AppReq app, User user) {
app.createdBy(user.getName());
AppDO appDO = new AppDO();
BeanMapper.mapper(app, appDO);
appDO.setStatus(AppStatus.INIT.getCode());
appDO.setConfig(JSONObject.toJSONString(app.getConfig()));
appDO.setAppSecret(getUniqueId());
appMapper.insert(appDO);
return convertDetail(appDO);
}
@Override
public AppDetailResp update(AppReq app, User user) {
app.updatedBy(user.getName());
AppDO appDO = getById(app.getId());
checkAuth(appDO, user);
BeanMapper.mapper(app, appDO);
appDO.setConfig(JSONObject.toJSONString(app.getConfig()));
appMapper.updateById(appDO);
return convertDetail(appDO);
}
@Override
public void online(Integer id, User user) {
AppDO appDO = getAppDO(id);
checkAuth(appDO, user);
appDO.setStatus(AppStatus.ONLINE.getCode());
appDO.setUpdatedAt(new Date());
appDO.setUpdatedBy(user.getName());
updateById(appDO);
}
@Override
public void offline(Integer id, User user) {
AppDO appDO = getAppDO(id);
checkAuth(appDO, user);
appDO.setStatus(AppStatus.OFFLINE.getCode());
appDO.setUpdatedAt(new Date());
appDO.setUpdatedBy(user.getName());
updateById(appDO);
}
@Override
public void delete(Integer id, User user) {
AppDO appDO = getAppDO(id);
checkAuth(appDO, user);
appDO.setStatus(AppStatus.DELETED.getCode());
appDO.setUpdatedAt(new Date());
appDO.setUpdatedBy(user.getName());
updateById(appDO);
}
@Override
public PageInfo<AppResp> pageApp(AppQueryReq appQueryReq, User user) {
PageInfo<AppDO> appDOPageInfo = PageHelper.startPage(appQueryReq.getCurrent(),
appQueryReq.getPageSize())
.doSelectPageInfo(() -> queryApp(appQueryReq));
PageInfo<AppResp> appPageInfo = PageUtils.pageInfo2PageInfoVo(appDOPageInfo);
Map<Long, MetricResp> metricResps = metricService.getMetrics(new MetaFilter())
.stream().collect(Collectors.toMap(MetricResp::getId, m -> m));
Map<Long, DimensionResp> dimensionResps = dimensionService.getDimensions(new MetaFilter())
.stream().collect(Collectors.toMap(DimensionResp::getId, m -> m));
appPageInfo.setList(appDOPageInfo.getList().stream().map(appDO
-> convert(appDO, dimensionResps, metricResps, user))
.collect(Collectors.toList()));
return appPageInfo;
}
public List<AppDO> queryApp(AppQueryReq appQueryReq) {
QueryWrapper<AppDO> appDOQueryWrapper = new QueryWrapper<>();
appDOQueryWrapper.lambda().ne(AppDO::getStatus, AppStatus.DELETED.getCode());
if (StringUtils.isNotBlank(appQueryReq.getName())) {
appDOQueryWrapper.lambda().like(AppDO::getName, appQueryReq.getName());
}
if (!CollectionUtils.isEmpty(appQueryReq.getStatus())) {
appDOQueryWrapper.lambda().in(AppDO::getStatus, appQueryReq.getStatus());
}
if (StringUtils.isNotBlank(appQueryReq.getCreatedBy())) {
appDOQueryWrapper.lambda().eq(AppDO::getCreatedBy, appQueryReq.getCreatedBy());
}
return list(appDOQueryWrapper);
}
@Override
public AppDetailResp getApp(Integer id, User user) {
AppDO appDO = getAppDO(id);
Map<Long, MetricResp> metricResps = metricService.getMetrics(new MetaFilter())
.stream().collect(Collectors.toMap(MetricResp::getId, m -> m));
Map<Long, DimensionResp> dimensionResps = dimensionService.getDimensions(new MetaFilter())
.stream().collect(Collectors.toMap(DimensionResp::getId, m -> m));
checkAuth(appDO, user);
return convertDetail(appDO, dimensionResps, metricResps);
}
@Override
public AppDetailResp getApp(Integer id) {
AppDO appDO = getAppDO(id);
return convertDetail(appDO, new HashMap<>(), new HashMap<>());
}
private AppDO getAppDO(Integer id) {
AppDO appDO = getById(id);
if (appDO == null) {
throw new InvalidArgumentException("该应用不存在");
}
return appDO;
}
private void checkAuth(AppDO appDO, User user) {
if (!hasAuth(appDO, user)) {
throw new InvalidPermissionException("您不是该应用的负责人, 暂无权查看或者修改");
}
}
private boolean hasAuth(AppDO appDO, User user) {
if (appDO.getCreatedBy().equalsIgnoreCase(user.getName())) {
return true;
}
return StringUtils.isNotBlank(appDO.getOwner())
&& appDO.getOwner().contains(user.getName());
}
private AppResp convert(AppDO appDO, Map<Long, DimensionResp> dimensionMap,
Map<Long, MetricResp> metricMap, User user) {
AppResp app = new AppResp();
BeanMapper.mapper(appDO, app);
AppConfig appConfig = JSONObject.parseObject(appDO.getConfig(), AppConfig.class);
fillItemName(appConfig, dimensionMap, metricMap);
app.setConfig(appConfig);
app.setAppStatus(AppStatus.fromCode(appDO.getStatus()));
app.setHasAdminRes(hasAuth(appDO, user));
return app;
}
private AppDetailResp convertDetail(AppDO appDO) {
return convertDetail(appDO, new HashMap<>(), new HashMap<>());
}
private AppDetailResp convertDetail(AppDO appDO, Map<Long, DimensionResp> dimensionMap,
Map<Long, MetricResp> metricMap) {
AppDetailResp app = new AppDetailResp();
BeanMapper.mapper(appDO, app);
AppConfig appConfig = JSONObject.parseObject(appDO.getConfig(), AppConfig.class);
fillItemName(appConfig, dimensionMap, metricMap);
app.setConfig(appConfig);
app.setAppStatus(AppStatus.fromCode(appDO.getStatus()));
return app;
}
private void fillItemName(AppConfig appConfig, Map<Long, DimensionResp> dimensionMap,
Map<Long, MetricResp> metricMap) {
appConfig.getItems().forEach(metricItem -> {
metricItem.setName(metricMap.getOrDefault(metricItem.getId(), new MetricResp()).getName());
metricItem.setBizName(metricMap.getOrDefault(metricItem.getId(), new MetricResp()).getBizName());
metricItem.setCreatedBy(metricMap.getOrDefault(metricItem.getId(), new MetricResp()).getCreatedBy());
metricItem.getRelateItems().forEach(dimensionItem -> {
dimensionItem.setName(dimensionMap.getOrDefault(dimensionItem.getId(), new DimensionResp()).getName());
dimensionItem.setBizName(dimensionMap.getOrDefault(dimensionItem.getId(),
new DimensionResp()).getBizName());
dimensionItem.setCreatedBy(dimensionMap.getOrDefault(dimensionItem.getId(),
new DimensionResp()).getCreatedBy());
});
});
}
private String getUniqueId() {
return UUID.randomUUID().toString().replaceAll("_", "");
}
}

View File

@@ -0,0 +1,120 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DataModelYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.MetricYamlTpl;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.Catalog;
import com.tencent.supersonic.headless.server.service.DatabaseService;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.MetricService;
import com.tencent.supersonic.headless.server.service.ModelRelaService;
import com.tencent.supersonic.headless.server.service.ModelService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Component
public class CatalogImpl implements Catalog {
private final DatabaseService databaseService;
private final ModelService modelService;
private final DimensionService dimensionService;
private final ModelService datasourceService;
private final MetricService metricService;
private final ModelRelaService modelRelaService;
public CatalogImpl(DatabaseService databaseService,
ModelService modelService, DimensionService dimensionService,
ModelService datasourceService,
MetricService metricService, ModelRelaService modelRelaService) {
this.databaseService = databaseService;
this.modelService = modelService;
this.dimensionService = dimensionService;
this.datasourceService = datasourceService;
this.metricService = metricService;
this.modelRelaService = modelRelaService;
}
public DatabaseResp getDatabase(Long id) {
return databaseService.getDatabase(id);
}
public DatabaseResp getDatabaseByModelId(Long modelId) {
return modelService.getDatabaseByModelId(modelId);
}
@Override
public String getModelFullPath(List<Long> modelIds) {
return String.join(",", modelIds.stream().map(Object::toString).collect(Collectors.toList()));
}
@Override
public DimensionResp getDimension(String bizName, Long modelId) {
return dimensionService.getDimension(bizName, modelId);
}
@Override
public DimensionResp getDimension(Long id) {
return dimensionService.getDimension(id);
}
@Override
public List<ModelRela> getModelRela(List<Long> modelIds) {
return modelRelaService.getModelRela(modelIds);
}
@Override
public List<DimensionResp> getDimensions(MetaFilter metaFilter) {
return dimensionService.getDimensions(metaFilter);
}
@Override
public List<MetricResp> getMetrics(MetaFilter metaFilter) {
return metricService.getMetrics(metaFilter);
}
@Override
public MetricResp getMetric(Long id) {
return metricService.getMetric(id);
}
@Override
public ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric) {
return datasourceService.getItemDate(dimension, metric);
}
@Override
public List<ModelResp> getModelList(List<Long> modelIds) {
List<ModelResp> modelRespList = new ArrayList<>();
if (!CollectionUtils.isEmpty(modelIds)) {
modelIds.stream().forEach(m -> {
modelRespList.add(modelService.getModel(m));
});
}
return modelRespList;
}
@Override
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName) {
datasourceService.getModelYamlTplByModelIds(modelIds, dimensionYamlMap, dataModelYamlTplList,
metricYamlTplList, modelIdName);
}
}

View File

@@ -0,0 +1,52 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.server.persistence.dataobject.CollectDO;
import com.tencent.supersonic.headless.server.persistence.mapper.CollectMapper;
import com.tencent.supersonic.headless.server.service.CollectService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Service
public class CollectServiceImpl implements CollectService {
public static final String type = "metric";
@Resource
private CollectMapper collectMapper;
@Override
public Boolean createCollectionIndicators(User user, Long id) {
CollectDO collectDO = new CollectDO();
collectDO.setType(type);
collectDO.setUsername(user.getName());
collectDO.setCollectId(id);
collectMapper.insert(collectDO);
return true;
}
@Override
public Boolean deleteCollectionIndicators(User user, Long id) {
QueryWrapper<CollectDO> collectDOQueryWrapper = new QueryWrapper<>();
collectDOQueryWrapper.lambda().eq(CollectDO::getUsername, user.getName());
collectDOQueryWrapper.lambda().eq(CollectDO::getCollectId, id);
collectDOQueryWrapper.lambda().eq(CollectDO::getType, type);
collectMapper.delete(collectDOQueryWrapper);
return true;
}
@Override
public List<CollectDO> getCollectList(String username) {
QueryWrapper<CollectDO> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(username)) {
queryWrapper.lambda().eq(CollectDO::getUsername, username);
}
return collectMapper.selectList(queryWrapper);
}
}

View File

@@ -0,0 +1,174 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.common.server.request.DatabaseReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.common.server.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.headless.server.engineadapter.EngineAdaptor;
import com.tencent.supersonic.headless.server.engineadapter.EngineAdaptorFactory;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDO;
import com.tencent.supersonic.headless.server.persistence.repository.DatabaseRepository;
import com.tencent.supersonic.headless.server.pojo.Database;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import com.tencent.supersonic.headless.server.service.DatabaseService;
import com.tencent.supersonic.headless.server.service.ModelService;
import com.tencent.supersonic.headless.server.utils.DatabaseConverter;
import com.tencent.supersonic.headless.server.utils.JdbcDataSourceUtils;
import com.tencent.supersonic.headless.server.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class DatabaseServiceImpl implements DatabaseService {
private final SqlUtils sqlUtils;
private DatabaseRepository databaseRepository;
private ModelService datasourceService;
public DatabaseServiceImpl(DatabaseRepository databaseRepository,
SqlUtils sqlUtils,
@Lazy ModelService datasourceService) {
this.databaseRepository = databaseRepository;
this.sqlUtils = sqlUtils;
this.datasourceService = datasourceService;
}
@Override
public boolean testConnect(DatabaseReq databaseReq, User user) {
Database database = DatabaseConverter.convert(databaseReq);
return JdbcDataSourceUtils.testDatabase(database);
}
@Override
public DatabaseResp createOrUpdateDatabase(DatabaseReq databaseReq, User user) {
Database database = DatabaseConverter.convert(databaseReq);
DatabaseDO databaseDO = getDatabaseDO(databaseReq.getId());
if (databaseDO != null) {
database.updatedBy(user.getName());
DatabaseConverter.convert(database, databaseDO);
databaseRepository.updateDatabase(databaseDO);
return DatabaseConverter.convert(databaseDO);
}
database.createdBy(user.getName());
databaseDO = DatabaseConverter.convert(database);
databaseRepository.createDatabase(databaseDO);
return DatabaseConverter.convert(databaseDO);
}
@Override
public List<DatabaseResp> getDatabaseList(User user) {
List<DatabaseResp> databaseResps =
databaseRepository.getDatabaseList()
.stream().map(DatabaseConverter::convert)
.collect(Collectors.toList());
fillPermission(databaseResps, user);
return databaseResps;
}
private void fillPermission(List<DatabaseResp> databaseResps, User user) {
databaseResps.forEach(databaseResp -> {
if (databaseResp.getAdmins().contains(user.getName())
|| user.getName().equalsIgnoreCase(databaseResp.getCreatedBy())
|| user.isSuperAdmin()) {
databaseResp.setHasPermission(true);
databaseResp.setHasEditPermission(true);
databaseResp.setHasUsePermission(true);
}
if (databaseResp.getViewers().contains(user.getName())) {
databaseResp.setHasUsePermission(true);
}
});
}
@Override
public void deleteDatabase(Long databaseId) {
ModelFilter modelFilter = new ModelFilter();
modelFilter.setDatabaseId(databaseId);
List<ModelResp> modelResps = datasourceService.getModelList(modelFilter);
if (!CollectionUtils.isEmpty(modelResps)) {
List<String> datasourceNames = modelResps.stream()
.map(ModelResp::getName).collect(Collectors.toList());
String message = String.format("该数据库被模型%s使用无法删除", datasourceNames);
throw new RuntimeException(message);
}
databaseRepository.deleteDatabase(databaseId);
}
@Override
public DatabaseResp getDatabase(Long id) {
DatabaseDO databaseDO = databaseRepository.getDatabase(id);
return DatabaseConverter.convert(databaseDO);
}
@Override
public QueryResultWithSchemaResp executeSql(String sql, Long id, User user) {
DatabaseResp databaseResp = getDatabase(id);
if (databaseResp == null) {
return new QueryResultWithSchemaResp();
}
List<String> admins = databaseResp.getAdmins();
List<String> viewers = databaseResp.getViewers();
if (!admins.contains(user.getName())
&& !viewers.contains(user.getName())
&& !databaseResp.getCreatedBy().equalsIgnoreCase(user.getName())
&& !user.isSuperAdmin()) {
String message = String.format("您暂无当前数据库%s权限, 请联系数据库管理员%s开通",
databaseResp.getName(),
String.join(",", admins));
throw new RuntimeException(message);
}
return executeSql(sql, databaseResp);
}
@Override
public QueryResultWithSchemaResp executeSql(String sql, DatabaseResp databaseResp) {
return queryWithColumns(sql, databaseResp);
}
private QueryResultWithSchemaResp queryWithColumns(String sql, DatabaseResp databaseResp) {
QueryResultWithSchemaResp queryResultWithColumns = new QueryResultWithSchemaResp();
SqlUtils sqlUtils = this.sqlUtils.init(databaseResp);
log.info("query SQL: {}", sql);
sqlUtils.queryInternal(sql, queryResultWithColumns);
return queryResultWithColumns;
}
private DatabaseDO getDatabaseDO(Long id) {
return databaseRepository.getDatabase(id);
}
@Override
public QueryResultWithSchemaResp getDbNames(Long id) {
DatabaseResp databaseResp = getDatabase(id);
EngineAdaptor engineAdaptor = EngineAdaptorFactory.getEngineAdaptor(databaseResp.getType());
String metaQueryTpl = engineAdaptor.getDbMetaQueryTpl();
return queryWithColumns(metaQueryTpl, databaseResp);
}
@Override
public QueryResultWithSchemaResp getTables(Long id, String db) {
DatabaseResp databaseResp = getDatabase(id);
EngineAdaptor engineAdaptor = EngineAdaptorFactory.getEngineAdaptor(databaseResp.getType());
String metaQueryTpl = engineAdaptor.getTableMetaQueryTpl();
String metaQuerySql = String.format(metaQueryTpl, db);
return queryWithColumns(metaQuerySql, databaseResp);
}
@Override
public QueryResultWithSchemaResp getColumns(Long id, String db, String table) {
DatabaseResp databaseResp = getDatabase(id);
EngineAdaptor engineAdaptor = EngineAdaptorFactory.getEngineAdaptor(databaseResp.getType());
String metaQueryTpl = engineAdaptor.getColumnMetaQueryTpl();
String metaQuerySql = String.format(metaQueryTpl, db, table);
return queryWithColumns(metaQuerySql, databaseResp);
}
}

View File

@@ -0,0 +1,367 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.DataItem;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.util.ChatGptHelper;
import com.tencent.supersonic.headless.common.server.pojo.DimValueMap;
import com.tencent.supersonic.headless.common.server.pojo.ModelDetail;
import com.tencent.supersonic.headless.common.server.request.DimensionReq;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.PageDimensionReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.common.server.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import com.tencent.supersonic.headless.server.persistence.repository.DimensionRepository;
import com.tencent.supersonic.headless.server.pojo.DimensionFilter;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.DatabaseService;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.ModelRelaService;
import com.tencent.supersonic.headless.server.service.ModelService;
import com.tencent.supersonic.headless.server.utils.DimensionConverter;
import com.tencent.supersonic.headless.server.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
public class DimensionServiceImpl implements DimensionService {
private DimensionRepository dimensionRepository;
private ModelService modelService;
private ChatGptHelper chatGptHelper;
private DatabaseService databaseService;
private ModelRelaService modelRelaService;
@Autowired
private ApplicationEventPublisher eventPublisher;
public DimensionServiceImpl(DimensionRepository dimensionRepository,
ModelService modelService,
ChatGptHelper chatGptHelper,
DatabaseService databaseService,
ModelRelaService modelRelaService) {
this.modelService = modelService;
this.dimensionRepository = dimensionRepository;
this.chatGptHelper = chatGptHelper;
this.databaseService = databaseService;
this.modelRelaService = modelRelaService;
}
@Override
public void createDimension(DimensionReq dimensionReq, User user) {
checkExist(Lists.newArrayList(dimensionReq));
dimensionReq.createdBy(user.getName());
DimensionDO dimensionDO = DimensionConverter.convert2DimensionDO(dimensionReq);
dimensionRepository.createDimension(dimensionDO);
sendEventBatch(Lists.newArrayList(dimensionDO), EventType.ADD);
}
@Override
public void createDimensionBatch(List<DimensionReq> dimensionReqs, User user) {
if (CollectionUtils.isEmpty(dimensionReqs)) {
return;
}
Long modelId = dimensionReqs.get(0).getModelId();
List<DimensionResp> dimensionResps = getDimensionInSameDomain(modelId);
Map<String, DimensionResp> bizNameMap = dimensionResps.stream()
.collect(Collectors.toMap(DimensionResp::getBizName, a -> a, (k1, k2) -> k1));
Map<String, DimensionResp> nameMap = dimensionResps.stream()
.collect(Collectors.toMap(DimensionResp::getName, a -> a, (k1, k2) -> k1));
List<DimensionReq> dimensionToInsert = dimensionReqs.stream()
.filter(dimension -> !bizNameMap.containsKey(dimension.getBizName())
&& !nameMap.containsKey(dimension.getName()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(dimensionToInsert)) {
return;
}
List<DimensionDO> dimensionDOS = dimensionToInsert.stream().peek(dimension ->
dimension.createdBy(user.getName()))
.map(DimensionConverter::convert2DimensionDO)
.collect(Collectors.toList());
dimensionRepository.createDimensionBatch(dimensionDOS);
sendEventBatch(dimensionDOS, EventType.ADD);
}
@Override
public void updateDimension(DimensionReq dimensionReq, User user) {
checkExist(Lists.newArrayList(dimensionReq));
DimensionDO dimensionDO = dimensionRepository.getDimensionById(dimensionReq.getId());
dimensionReq.updatedBy(user.getName());
String oldName = dimensionDO.getName();
DimensionConverter.convert(dimensionDO, dimensionReq);
dimensionRepository.updateDimension(dimensionDO);
if (!oldName.equals(dimensionDO.getName())) {
sendEvent(DataItem.builder().modelId(dimensionDO.getModelId()).newName(dimensionReq.getName())
.name(oldName).type(TypeEnums.DIMENSION)
.id(dimensionDO.getId()).build(), EventType.UPDATE);
}
}
@Override
public void batchUpdateStatus(MetaBatchReq metaBatchReq, User user) {
if (CollectionUtils.isEmpty(metaBatchReq.getIds())) {
return;
}
DimensionFilter dimensionFilter = new DimensionFilter();
dimensionFilter.setIds(metaBatchReq.getIds());
List<DimensionDO> dimensionDOS = dimensionRepository.getDimension(dimensionFilter);
if (CollectionUtils.isEmpty(dimensionDOS)) {
return;
}
dimensionDOS = dimensionDOS.stream()
.peek(dimensionDO -> {
dimensionDO.setStatus(metaBatchReq.getStatus());
dimensionDO.setUpdatedAt(new Date());
dimensionDO.setUpdatedBy(user.getName());
})
.collect(Collectors.toList());
dimensionRepository.batchUpdateStatus(dimensionDOS);
if (StatusEnum.OFFLINE.getCode().equals(metaBatchReq.getStatus())
|| StatusEnum.DELETED.getCode().equals(metaBatchReq.getStatus())) {
sendEventBatch(dimensionDOS, EventType.DELETE);
} else if (StatusEnum.ONLINE.getCode().equals(metaBatchReq.getStatus())) {
sendEventBatch(dimensionDOS, EventType.ADD);
}
}
@Override
public void deleteDimension(Long id, User user) {
DimensionDO dimensionDO = dimensionRepository.getDimensionById(id);
if (dimensionDO == null) {
throw new RuntimeException(String.format("the dimension %s not exist", id));
}
dimensionDO.setStatus(StatusEnum.DELETED.getCode());
dimensionDO.setUpdatedAt(new Date());
dimensionDO.setUpdatedBy(user.getName());
dimensionRepository.updateDimension(dimensionDO);
sendEventBatch(Lists.newArrayList(dimensionDO), EventType.DELETE);
}
@Override
public DimensionResp getDimension(String bizName, Long modelId) {
List<DimensionResp> dimensionResps = getDimensions(modelId);
if (CollectionUtils.isEmpty(dimensionResps)) {
return null;
}
for (DimensionResp dimensionResp : dimensionResps) {
if (dimensionResp.getBizName().equalsIgnoreCase(bizName)) {
return dimensionResp;
}
}
return null;
}
@Override
public DimensionResp getDimension(Long id) {
DimensionDO dimensionDO = dimensionRepository.getDimensionById(id);
if (dimensionDO == null) {
return null;
}
return DimensionConverter.convert2DimensionResp(dimensionDO, new HashMap<>());
}
@Override
public PageInfo<DimensionResp> queryDimension(PageDimensionReq pageDimensionReq) {
DimensionFilter dimensionFilter = new DimensionFilter();
BeanUtils.copyProperties(pageDimensionReq, dimensionFilter);
dimensionFilter.setModelIds(pageDimensionReq.getModelIds());
PageInfo<DimensionDO> dimensionDOPageInfo = PageHelper.startPage(pageDimensionReq.getCurrent(),
pageDimensionReq.getPageSize())
.doSelectPageInfo(() -> queryDimension(dimensionFilter));
PageInfo<DimensionResp> pageInfo = new PageInfo<>();
BeanUtils.copyProperties(dimensionDOPageInfo, pageInfo);
pageInfo.setList(convertList(dimensionDOPageInfo.getList(), modelService.getModelMap()));
return pageInfo;
}
private List<DimensionDO> queryDimension(DimensionFilter dimensionFilter) {
return dimensionRepository.getDimension(dimensionFilter);
}
@Override
public List<DimensionResp> getDimensions(MetaFilter metaFilter) {
DimensionFilter dimensionFilter = new DimensionFilter();
BeanUtils.copyProperties(metaFilter, dimensionFilter);
List<DimensionDO> dimensionDOS = dimensionRepository.getDimension(dimensionFilter);
return convertList(dimensionDOS, modelService.getModelMap());
}
private List<DimensionResp> getDimensions(Long modelId) {
return getDimensions(new MetaFilter(Lists.newArrayList(modelId)));
}
@Override
public List<DimensionResp> getDimensionInModelCluster(Long modelId) {
ModelResp modelResp = modelService.getModel(modelId);
List<ModelRela> modelRelas = modelRelaService.getModelRelaList(modelResp.getDomainId());
List<Long> modelIds = new ArrayList<>();
modelIds.add(modelId);
for (ModelRela modelRela : modelRelas) {
modelIds.add(modelRela.getFromModelId());
modelIds.add(modelRela.getToModelId());
}
DimensionFilter dimensionFilter = new DimensionFilter();
dimensionFilter.setModelIds(modelIds);
return getDimensions(dimensionFilter);
}
private List<DimensionResp> convertList(List<DimensionDO> dimensionDOS,
Map<Long, ModelResp> modelRespMap) {
List<DimensionResp> dimensionResps = Lists.newArrayList();
if (!CollectionUtils.isEmpty(dimensionDOS)) {
dimensionResps = dimensionDOS.stream()
.map(dimensionDO -> DimensionConverter
.convert2DimensionResp(dimensionDO, modelRespMap))
.collect(Collectors.toList());
}
return dimensionResps;
}
@Override
public List<String> mockAlias(DimensionReq dimensionReq, String mockType, User user) {
String mockAlias = chatGptHelper.mockAlias(mockType, dimensionReq.getName(), dimensionReq.getBizName(),
"", dimensionReq.getDescription(), false);
return JSONObject.parseObject(mockAlias, new TypeReference<List<String>>() {
});
}
@Override
public List<DimValueMap> mockDimensionValueAlias(DimensionReq dimensionReq, User user) {
ModelResp modelResp = modelService.getModel(dimensionReq.getModelId());
ModelDetail modelDetail = modelResp.getModelDetail();
String sqlQuery = modelDetail.getSqlQuery();
DatabaseResp database = databaseService.getDatabase(modelResp.getDatabaseId());
String sql = "select ai_talk." + dimensionReq.getBizName() + " from (" + sqlQuery
+ ") as ai_talk group by ai_talk." + dimensionReq.getBizName();
QueryResultWithSchemaResp queryResultWithSchemaResp = databaseService.executeSql(sql, database);
List<Map<String, Object>> resultList = queryResultWithSchemaResp.getResultList();
List<String> valueList = new ArrayList<>();
for (Map<String, Object> stringObjectMap : resultList) {
String value = (String) stringObjectMap.get(dimensionReq.getBizName());
valueList.add(value);
}
String json = chatGptHelper.mockDimensionValueAlias(JSON.toJSONString(valueList));
log.info("return llm res is :{}", json);
JSONObject jsonObject = JSON.parseObject(json);
List<DimValueMap> dimValueMapsResp = new ArrayList<>();
int i = 0;
for (Map<String, Object> stringObjectMap : resultList) {
DimValueMap dimValueMap = new DimValueMap();
dimValueMap.setTechName(String.valueOf(stringObjectMap.get(dimensionReq.getBizName())));
try {
String tran = jsonObject.getJSONArray("tran").getString(i);
dimValueMap.setBizName(tran);
} catch (Exception exception) {
dimValueMap.setBizName("");
}
try {
dimValueMap.setAlias(jsonObject.getJSONObject("alias")
.getJSONArray(stringObjectMap.get(dimensionReq.getBizName()) + "").toJavaList(String.class));
} catch (Exception exception) {
dimValueMap.setAlias(null);
}
dimValueMapsResp.add(dimValueMap);
i++;
}
return dimValueMapsResp;
}
private List<DimensionResp> getDimensionInSameDomain(Long modelId) {
ModelResp modelResp = modelService.getModel(modelId);
Long domainId = modelResp.getDomainId();
List<ModelResp> modelResps = modelService.getModelByDomainIds(Lists.newArrayList(domainId));
List<Long> modelIds = modelResps.stream().map(ModelResp::getId).collect(Collectors.toList());
return getDimensions(new MetaFilter(modelIds));
}
private void checkExist(List<DimensionReq> dimensionReqs) {
Long modelId = dimensionReqs.get(0).getModelId();
List<DimensionResp> dimensionResps = getDimensionInSameDomain(modelId);
Map<String, DimensionResp> bizNameMap = dimensionResps.stream()
.collect(Collectors.toMap(DimensionResp::getBizName, a -> a, (k1, k2) -> k1));
Map<String, DimensionResp> nameMap = dimensionResps.stream()
.collect(Collectors.toMap(DimensionResp::getName, a -> a, (k1, k2) -> k1));
for (DimensionReq dimensionReq : dimensionReqs) {
if (NameCheckUtils.containsSpecialCharacters(dimensionReq.getName())) {
throw new InvalidArgumentException("名称包含特殊字符, 请修改");
}
if (bizNameMap.containsKey(dimensionReq.getBizName())) {
DimensionResp dimensionResp = bizNameMap.get(dimensionReq.getBizName());
if (!dimensionResp.getId().equals(dimensionReq.getId())) {
throw new RuntimeException(String.format("该模型下存在相同的维度字段名:%s 创建人:%s",
dimensionReq.getBizName(), dimensionResp.getCreatedBy()));
}
}
if (nameMap.containsKey(dimensionReq.getName())) {
DimensionResp dimensionResp = nameMap.get(dimensionReq.getName());
if (!dimensionResp.getId().equals(dimensionReq.getId())) {
throw new RuntimeException(String.format("该模型下存在相同的维度名:%s 创建人:%s",
dimensionReq.getName(), dimensionResp.getCreatedBy()));
}
}
}
}
@Override
public void sendDimensionEventBatch(List<Long> modelIds, EventType eventType) {
DimensionFilter dimensionFilter = new DimensionFilter();
dimensionFilter.setModelIds(modelIds);
List<DimensionDO> dimensionDOS = queryDimension(dimensionFilter);
sendEventBatch(dimensionDOS, eventType);
}
private void sendEventBatch(List<DimensionDO> dimensionDOS, EventType eventType) {
List<DataItem> dataItems = dimensionDOS.stream().map(dimensionDO ->
DataItem.builder().id(dimensionDO.getId()).name(dimensionDO.getName())
.modelId(dimensionDO.getModelId()).type(TypeEnums.DIMENSION).build())
.collect(Collectors.toList());
eventPublisher.publishEvent(new DataEvent(this, dataItems, eventType));
}
private void sendEvent(DataItem dataItem, EventType eventType) {
eventPublisher.publishEvent(new DataEvent(this,
Lists.newArrayList(dataItem), eventType));
}
private DataItem getDataItem(DimensionDO dimensionDO) {
return DataItem.builder().id(dimensionDO.getId()).name(dimensionDO.getName())
.bizName(dimensionDO.getBizName())
.modelId(dimensionDO.getModelId()).type(TypeEnums.DIMENSION).build();
}
}

View File

@@ -0,0 +1,274 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.headless.common.server.request.DomainReq;
import com.tencent.supersonic.headless.common.server.request.DomainUpdateReq;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO;
import com.tencent.supersonic.headless.server.persistence.repository.DomainRepository;
import com.tencent.supersonic.headless.server.service.DomainService;
import com.tencent.supersonic.headless.server.service.ModelService;
import com.tencent.supersonic.headless.server.utils.DomainConvert;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Sets;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Slf4j
public class DomainServiceImpl implements DomainService {
private final DomainRepository domainRepository;
private final ModelService modelService;
private final UserService userService;
public DomainServiceImpl(DomainRepository domainRepository,
@Lazy ModelService modelService,
UserService userService) {
this.domainRepository = domainRepository;
this.modelService = modelService;
this.userService = userService;
}
@Override
public void createDomain(DomainReq domainReq, User user) {
DomainDO domainDO = DomainConvert.convert(domainReq, user);
domainDO.setStatus(StatusEnum.ONLINE.getCode());
domainRepository.createDomain(domainDO);
}
@Override
public void updateDomain(DomainUpdateReq domainUpdateReq, User user) {
domainUpdateReq.updatedBy(user.getName());
DomainDO domainDO = getDomainDO(domainUpdateReq.getId());
BeanMapper.mapper(domainUpdateReq, domainDO);
domainRepository.updateDomain(domainDO);
}
@Override
public void deleteDomain(Long id) {
List<ModelResp> modelResps = modelService.getModelByDomainIds(Lists.newArrayList(id));
if (!CollectionUtils.isEmpty(modelResps)) {
throw new RuntimeException("该主题域下还存在模型, 暂不能删除, 请确认");
}
domainRepository.deleteDomain(id);
}
@Override
public List<DomainResp> getDomainList() {
return convertList(domainRepository.getDomainList());
}
@Override
public List<DomainResp> getDomainList(List<Long> domainIds) {
return getDomainList().stream()
.filter(domainDO -> domainIds.contains(domainDO.getId()))
.collect(Collectors.toList());
}
@Override
public List<DomainResp> getDomainListWithAdminAuth(User user) {
Set<DomainResp> domainWithAuthAll = getDomainAuthSet(user, AuthType.ADMIN);
if (!CollectionUtils.isEmpty(domainWithAuthAll)) {
List<Long> domainIds = domainWithAuthAll.stream().map(DomainResp::getId).collect(Collectors.toList());
domainWithAuthAll.addAll(getParentDomain(domainIds));
}
List<ModelResp> modelResps = modelService.getModelAuthList(user, AuthType.ADMIN);
if (!CollectionUtils.isEmpty(modelResps)) {
List<Long> domainIds = modelResps.stream().map(ModelResp::getDomainId).collect(Collectors.toList());
domainWithAuthAll.addAll(getParentDomain(domainIds));
}
return new ArrayList<>(domainWithAuthAll).stream()
.sorted(Comparator.comparingLong(DomainResp::getId)).collect(Collectors.toList());
}
@Override
public Set<DomainResp> getDomainAuthSet(User user, AuthType authTypeEnum) {
List<DomainResp> domainResps = getDomainList();
Set<String> orgIds = userService.getUserAllOrgId(user.getName());
List<DomainResp> domainWithAuth = Lists.newArrayList();
if (authTypeEnum.equals(AuthType.ADMIN)) {
domainWithAuth = domainResps.stream()
.filter(domainResp -> checkAdminPermission(orgIds, user, domainResp))
.collect(Collectors.toList());
}
if (authTypeEnum.equals(AuthType.VISIBLE)) {
domainWithAuth = domainResps.stream()
.filter(domainResp -> checkViewerPermission(orgIds, user, domainResp))
.collect(Collectors.toList());
}
List<Long> domainIds = domainWithAuth.stream().map(DomainResp::getId)
.collect(Collectors.toList());
//get all child domain
return getDomainChildren(domainIds).stream()
.peek(domainResp -> domainResp.setHasEditPermission(true))
.collect(Collectors.toSet());
}
private Set<DomainResp> getParentDomain(List<Long> ids) {
Set<DomainResp> domainSet = new HashSet<>();
if (CollectionUtils.isEmpty(ids)) {
return Sets.newHashSet(domainSet);
}
Map<Long, DomainResp> domainRespMap = getDomainMap();
for (Long domainId : ids) {
DomainResp domainResp = domainRespMap.get(domainId);
while (domainResp != null) {
domainSet.add(domainResp);
domainResp = domainRespMap.get(domainResp.getParentId());
}
}
return domainSet;
}
@Override
public DomainResp getDomain(Long id) {
Map<Long, String> fullDomainPathMap = getDomainFullPathMap();
return DomainConvert.convert(getDomainDO(id), fullDomainPathMap);
}
@Override
public Map<Long, String> getDomainFullPath() {
return getDomainFullPathMap();
}
private List<DomainResp> convertList(List<DomainDO> domainDOS) {
List<DomainResp> domainDescs = Lists.newArrayList();
if (CollectionUtils.isEmpty(domainDOS)) {
return domainDescs;
}
Map<Long, String> fullDomainPathMap = getDomainFullPath();
return domainDOS.stream()
.map(domainDO -> DomainConvert.convert(domainDO, fullDomainPathMap))
.collect(Collectors.toList());
}
@Override
public Map<Long, DomainResp> getDomainMap() {
return getDomainList().stream().collect(Collectors.toMap(DomainResp::getId, a -> a, (k1, k2) -> k1));
}
@Override
public Set<DomainResp> getDomainChildren(List<Long> domainIds) {
Set<DomainResp> childDomains = new HashSet<>();
if (CollectionUtils.isEmpty(domainIds)) {
return childDomains;
}
Map<Long, DomainResp> allDomainMap = getDomainMap();
for (Long domainId : domainIds) {
DomainResp domain = allDomainMap.get(domainId);
if (domain != null) {
childDomains.add(domain);
Queue<DomainResp> queue = new LinkedList<>();
queue.add(domain);
while (!queue.isEmpty()) {
DomainResp currentDomain = queue.poll();
for (DomainResp child : allDomainMap.values()) {
if (Objects.equals(child.getParentId(), currentDomain.getId())) {
childDomains.add(child);
queue.add(child);
}
}
}
}
}
return childDomains;
}
public Map<Long, String> getDomainFullPathMap() {
Map<Long, String> domainFullPathMap = new HashMap<>();
List<DomainDO> domainDOList = domainRepository.getDomainList();
Map<Long, DomainDO> domainDOMap = domainDOList.stream()
.collect(Collectors.toMap(DomainDO::getId, a -> a, (k1, k2) -> k1));
for (DomainDO domainDO : domainDOList) {
final Long domainId = domainDO.getId();
StringBuilder fullPath = new StringBuilder(domainDO.getBizName() + "/");
Long parentId = domainDO.getParentId();
while (parentId != null && parentId > 0) {
domainDO = domainDOMap.get(parentId);
if (domainDO == null) {
String message = String.format("get domain : %s failed", parentId);
throw new RuntimeException(message);
}
fullPath.insert(0, domainDO.getBizName() + "/");
parentId = domainDO.getParentId();
}
domainFullPathMap.put(domainId, fullPath.toString());
}
return domainFullPathMap;
}
protected DomainDO getDomainDO(Long id) {
return domainRepository.getDomainById(id);
}
private boolean checkAdminPermission(Set<String> orgIds, User user, DomainResp domainResp) {
List<String> admins = domainResp.getAdmins();
List<String> adminOrgs = domainResp.getAdminOrgs();
if (user.isSuperAdmin()) {
return true;
}
if (admins.contains(user.getName()) || domainResp.getCreatedBy().equals(user.getName())) {
return true;
}
if (CollectionUtils.isEmpty(adminOrgs)) {
return false;
}
for (String orgId : orgIds) {
if (adminOrgs.contains(orgId)) {
return true;
}
}
return false;
}
private boolean checkViewerPermission(Set<String> orgIds, User user, DomainResp domainDesc) {
List<String> admins = domainDesc.getAdmins();
List<String> viewers = domainDesc.getViewers();
List<String> adminOrgs = domainDesc.getAdminOrgs();
List<String> viewOrgs = domainDesc.getViewOrgs();
if (user.isSuperAdmin()) {
return true;
}
if (admins.contains(user.getName())
|| viewers.contains(user.getName())
|| domainDesc.getCreatedBy().equals(user.getName())) {
return true;
}
if (CollectionUtils.isEmpty(adminOrgs) && CollectionUtils.isEmpty(viewOrgs)) {
return false;
}
for (String orgId : orgIds) {
if (adminOrgs.contains(orgId)) {
return true;
}
}
for (String orgId : orgIds) {
if (viewOrgs.contains(orgId)) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,414 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.DataItem;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.ChatGptHelper;
import com.tencent.supersonic.headless.common.server.pojo.DrillDownDimension;
import com.tencent.supersonic.headless.common.server.pojo.Measure;
import com.tencent.supersonic.headless.common.server.pojo.MetricQueryDefaultConfig;
import com.tencent.supersonic.headless.common.server.pojo.MetricTypeParams;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.MetricReq;
import com.tencent.supersonic.headless.common.server.request.PageMetricReq;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.CollectDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.MetricQueryDefaultConfigDO;
import com.tencent.supersonic.headless.server.persistence.repository.MetricRepository;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.pojo.MetricFilter;
import com.tencent.supersonic.headless.server.service.CollectService;
import com.tencent.supersonic.headless.server.service.DomainService;
import com.tencent.supersonic.headless.server.service.MetricService;
import com.tencent.supersonic.headless.server.service.ModelService;
import com.tencent.supersonic.headless.server.utils.MetricConverter;
import com.tencent.supersonic.headless.server.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Slf4j
public class MetricServiceImpl implements MetricService {
private MetricRepository metricRepository;
private ModelService modelService;
private DomainService domainService;
private ChatGptHelper chatGptHelper;
private CollectService collectService;
private ApplicationEventPublisher eventPublisher;
public MetricServiceImpl(MetricRepository metricRepository,
ModelService modelService,
DomainService domainService,
ChatGptHelper chatGptHelper,
CollectService collectService,
ApplicationEventPublisher eventPublisher) {
this.domainService = domainService;
this.metricRepository = metricRepository;
this.modelService = modelService;
this.chatGptHelper = chatGptHelper;
this.eventPublisher = eventPublisher;
this.collectService = collectService;
}
@Override
public void createMetric(MetricReq metricReq, User user) {
checkExist(Lists.newArrayList(metricReq));
checkParam(metricReq);
metricReq.createdBy(user.getName());
MetricDO metricDO = MetricConverter.convert2MetricDO(metricReq);
metricRepository.createMetric(metricDO);
sendEventBatch(Lists.newArrayList(metricDO), EventType.ADD);
}
@Override
public void createMetricBatch(List<MetricReq> metricReqs, User user) {
if (CollectionUtils.isEmpty(metricReqs)) {
return;
}
Long modelId = metricReqs.get(0).getModelId();
List<MetricResp> metricResps = getMetricInSameDomain(modelId);
Map<String, MetricResp> bizNameMap = metricResps.stream()
.collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1));
Map<String, MetricResp> nameMap = metricResps.stream()
.collect(Collectors.toMap(MetricResp::getName, a -> a, (k1, k2) -> k1));
List<MetricReq> metricToInsert = metricReqs.stream()
.filter(metric -> !bizNameMap.containsKey(metric.getBizName())
&& !nameMap.containsKey(metric.getName())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(metricToInsert)) {
return;
}
List<MetricDO> metricDOS = metricToInsert.stream().peek(metric -> metric.createdBy(user.getName()))
.map(MetricConverter::convert2MetricDO).collect(Collectors.toList());
metricRepository.createMetricBatch(metricDOS);
sendEventBatch(metricDOS, EventType.ADD);
}
@Override
public void updateExprMetric(MetricReq metricReq, User user) {
checkParam(metricReq);
checkExist(Lists.newArrayList(metricReq));
metricReq.updatedBy(user.getName());
MetricDO metricDO = metricRepository.getMetricById(metricReq.getId());
String oldName = metricDO.getName();
MetricConverter.convert(metricDO, metricReq);
metricRepository.updateMetric(metricDO);
if (!oldName.equals(metricDO.getName())) {
DataItem dataItem = getDataItem(metricDO);
dataItem.setName(oldName);
dataItem.setNewName(metricDO.getName());
sendEvent(getDataItem(metricDO), EventType.UPDATE);
}
}
@Override
public void batchUpdateStatus(MetaBatchReq metaBatchReq, User user) {
if (CollectionUtils.isEmpty(metaBatchReq.getIds())) {
return;
}
MetricFilter metricFilter = new MetricFilter();
metricFilter.setIds(metaBatchReq.getIds());
List<MetricDO> metricDOS = metricRepository.getMetric(metricFilter);
if (CollectionUtils.isEmpty(metricDOS)) {
return;
}
metricDOS = metricDOS.stream()
.peek(metricDO -> {
metricDO.setStatus(metaBatchReq.getStatus());
metricDO.setUpdatedAt(new Date());
metricDO.setUpdatedBy(user.getName());
})
.collect(Collectors.toList());
metricRepository.batchUpdateStatus(metricDOS);
if (StatusEnum.OFFLINE.getCode().equals(metaBatchReq.getStatus())
|| StatusEnum.DELETED.getCode().equals(metaBatchReq.getStatus())) {
sendEventBatch(metricDOS, EventType.DELETE);
} else if (StatusEnum.ONLINE.getCode().equals(metaBatchReq.getStatus())) {
sendEventBatch(metricDOS, EventType.ADD);
}
}
@Override
public void deleteMetric(Long id, User user) {
MetricDO metricDO = metricRepository.getMetricById(id);
if (metricDO == null) {
throw new RuntimeException(String.format("the metric %s not exist", id));
}
metricDO.setStatus(StatusEnum.DELETED.getCode());
metricDO.setUpdatedAt(new Date());
metricDO.setUpdatedBy(user.getName());
metricRepository.updateMetric(metricDO);
sendEventBatch(Lists.newArrayList(metricDO), EventType.DELETE);
}
@Override
public PageInfo<MetricResp> queryMetric(PageMetricReq pageMetricReq, User user) {
MetricFilter metricFilter = new MetricFilter();
BeanUtils.copyProperties(pageMetricReq, metricFilter);
Set<DomainResp> domainResps = domainService.getDomainChildren(pageMetricReq.getDomainIds());
List<Long> domainIds = domainResps.stream().map(DomainResp::getId).collect(Collectors.toList());
List<ModelResp> modelResps = modelService.getModelByDomainIds(domainIds);
List<Long> modelIds = modelResps.stream().map(ModelResp::getId).collect(Collectors.toList());
pageMetricReq.getModelIds().addAll(modelIds);
metricFilter.setModelIds(pageMetricReq.getModelIds());
PageInfo<MetricDO> metricDOPageInfo = PageHelper.startPage(pageMetricReq.getCurrent(),
pageMetricReq.getPageSize())
.doSelectPageInfo(() -> queryMetric(metricFilter));
PageInfo<MetricResp> pageInfo = new PageInfo<>();
BeanUtils.copyProperties(metricDOPageInfo, pageInfo);
List<CollectDO> collectList = collectService.getCollectList(user.getName());
List<Long> collect = collectList.stream().map(CollectDO::getCollectId).collect(Collectors.toList());
List<MetricResp> metricResps = convertList(metricDOPageInfo.getList(), collect);
fillAdminRes(metricResps, user);
pageInfo.setList(metricResps);
return pageInfo;
}
protected List<MetricDO> queryMetric(MetricFilter metricFilter) {
return metricRepository.getMetric(metricFilter);
}
@Override
public List<MetricResp> getMetrics(MetaFilter metaFilter) {
MetricFilter metricFilter = new MetricFilter();
BeanUtils.copyProperties(metaFilter, metricFilter);
return convertList(queryMetric(metricFilter), Lists.newArrayList());
}
private void fillAdminRes(List<MetricResp> metricResps, User user) {
List<ModelResp> modelResps = modelService.getModelListWithAuth(user, null, AuthType.ADMIN);
if (CollectionUtils.isEmpty(modelResps)) {
return;
}
Set<Long> modelIdSet = modelResps.stream().map(ModelResp::getId).collect(Collectors.toSet());
for (MetricResp metricResp : metricResps) {
if (modelIdSet.contains(metricResp.getModelId())) {
metricResp.setHasAdminRes(true);
}
}
}
@Deprecated
@Override
public MetricResp getMetric(Long modelId, String bizName) {
MetricFilter metricFilter = new MetricFilter();
metricFilter.setBizName(bizName);
metricFilter.setModelIds(Lists.newArrayList(modelId));
List<MetricResp> metricResps = getMetrics(metricFilter);
MetricResp metricResp = null;
if (CollectionUtils.isEmpty(metricResps)) {
return metricResp;
}
return metricResps.get(0);
}
@Override
public MetricResp getMetric(Long id, User user) {
MetricResp metricResp = getMetric(id);
if (metricResp == null) {
return null;
}
fillAdminRes(Lists.newArrayList(metricResp), user);
return metricResp;
}
@Override
public MetricResp getMetric(Long id) {
MetricDO metricDO = metricRepository.getMetricById(id);
if (metricDO == null) {
return null;
}
return MetricConverter.convert2MetricResp(metricDO, new HashMap<>(), Lists.newArrayList());
}
@Override
public List<String> mockAlias(MetricReq metricReq, String mockType, User user) {
String mockAlias = chatGptHelper.mockAlias(mockType, metricReq.getName(), metricReq.getBizName(), "",
metricReq.getDescription(), !"".equals(metricReq.getDataFormatType()));
return JSONObject.parseObject(mockAlias, new TypeReference<List<String>>() {
});
}
@Override
public Set<String> getMetricTags() {
List<MetricResp> metricResps = getMetrics(new MetaFilter());
if (CollectionUtils.isEmpty(metricResps)) {
return new HashSet<>();
}
return metricResps.stream().flatMap(metricResp ->
metricResp.getTags().stream()).collect(Collectors.toSet());
}
@Override
public List<DrillDownDimension> getDrillDownDimension(Long metricId) {
MetricResp metricResp = getMetric(metricId);
if (metricResp == null) {
return Lists.newArrayList();
}
if (metricResp.getRelateDimension() != null
&& !CollectionUtils.isEmpty(metricResp.getRelateDimension().getDrillDownDimensions())) {
return metricResp.getRelateDimension().getDrillDownDimensions();
}
ModelResp modelResp = modelService.getModel(metricResp.getModelId());
return modelResp.getDrillDownDimensions();
}
@Override
public List<DataItem> getDataItems(Long modelId) {
MetricFilter metaFilter = new MetricFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
List<MetricDO> metricDOS = queryMetric(metaFilter);
if (CollectionUtils.isEmpty(metricDOS)) {
return Lists.newArrayList();
}
return metricDOS.stream().map(this::getDataItem).collect(Collectors.toList());
}
@Override
public void saveMetricQueryDefaultConfig(MetricQueryDefaultConfig defaultConfig, User user) {
MetricQueryDefaultConfigDO defaultConfigDO =
metricRepository.getDefaultQueryConfig(defaultConfig.getMetricId(), user.getName());
if (defaultConfigDO == null) {
defaultConfigDO = new MetricQueryDefaultConfigDO();
defaultConfig.createdBy(user.getName());
BeanMapper.mapper(defaultConfig, defaultConfigDO);
metricRepository.saveDefaultQueryConfig(defaultConfigDO);
} else {
defaultConfig.setId(defaultConfigDO.getId());
defaultConfig.updatedBy(user.getName());
BeanMapper.mapper(defaultConfig, defaultConfigDO);
metricRepository.updateDefaultQueryConfig(defaultConfigDO);
}
}
@Override
public MetricQueryDefaultConfig getMetricQueryDefaultConfig(Long metricId, User user) {
MetricQueryDefaultConfigDO metricQueryDefaultConfigDO =
metricRepository.getDefaultQueryConfig(metricId, user.getName());
MetricQueryDefaultConfig metricQueryDefaultConfig = new MetricQueryDefaultConfig();
BeanMapper.mapper(metricQueryDefaultConfigDO, metricQueryDefaultConfig);
return metricQueryDefaultConfig;
}
private void checkParam(MetricReq metricReq) {
MetricTypeParams typeParams = metricReq.getTypeParams();
List<Measure> measures = typeParams.getMeasures();
if (CollectionUtils.isEmpty(measures)) {
throw new InvalidArgumentException("不可缺少度量");
}
if (StringUtils.isBlank(typeParams.getExpr())) {
throw new InvalidArgumentException("表达式不可为空");
}
if (NameCheckUtils.containsSpecialCharacters(metricReq.getName())) {
throw new InvalidArgumentException("名称包含特殊字符, 请修改");
}
}
private void checkExist(List<MetricReq> metricReqs) {
Long modelId = metricReqs.get(0).getModelId();
List<MetricResp> metricResps = getMetricInSameDomain(modelId);
Map<String, MetricResp> bizNameMap = metricResps.stream()
.collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1));
Map<String, MetricResp> nameMap = metricResps.stream()
.collect(Collectors.toMap(MetricResp::getName, a -> a, (k1, k2) -> k1));
for (MetricReq metricReq : metricReqs) {
if (NameCheckUtils.containsSpecialCharacters(metricReq.getName())) {
throw new InvalidArgumentException("名称包含特殊字符, 请修改");
}
if (bizNameMap.containsKey(metricReq.getBizName())) {
MetricResp metricResp = bizNameMap.get(metricReq.getBizName());
if (!metricResp.getId().equals(metricReq.getId())) {
throw new RuntimeException(String.format("该主题域下存在相同的指标字段名:%s 创建人:%s",
metricReq.getBizName(), metricResp.getCreatedBy()));
}
}
if (nameMap.containsKey(metricReq.getName())) {
MetricResp metricResp = nameMap.get(metricReq.getName());
if (!metricResp.getId().equals(metricReq.getId())) {
throw new RuntimeException(String.format("该主题域下存在相同的指标名:%s 创建人:%s",
metricReq.getName(), metricResp.getCreatedBy()));
}
}
}
}
private List<MetricResp> getMetricInSameDomain(Long modelId) {
ModelResp modelResp = modelService.getModel(modelId);
Long domainId = modelResp.getDomainId();
List<ModelResp> modelResps = modelService.getModelByDomainIds(Lists.newArrayList(domainId));
List<Long> modelIds = modelResps.stream().map(ModelResp::getId).collect(Collectors.toList());
return getMetrics(new MetaFilter(modelIds));
}
private List<MetricResp> convertList(List<MetricDO> metricDOS, List<Long> collect) {
List<MetricResp> metricResps = Lists.newArrayList();
Map<Long, ModelResp> modelMap = modelService.getModelMap();
if (!CollectionUtils.isEmpty(metricDOS)) {
metricResps = metricDOS.stream()
.map(metricDO -> MetricConverter.convert2MetricResp(metricDO, modelMap, collect))
.collect(Collectors.toList());
}
return metricResps;
}
@Override
public void sendMetricEventBatch(List<Long> modelIds, EventType eventType) {
MetricFilter metricFilter = new MetricFilter();
metricFilter.setModelIds(modelIds);
List<MetricDO> metricDOS = queryMetric(metricFilter);
sendEventBatch(metricDOS, eventType);
}
private void sendEventBatch(List<MetricDO> metricDOS, EventType eventType) {
List<DataItem> dataItems = metricDOS.stream().map(this::getDataItem)
.collect(Collectors.toList());
eventPublisher.publishEvent(new DataEvent(this, dataItems, eventType));
}
private void sendEvent(DataItem dataItem, EventType eventType) {
eventPublisher.publishEvent(new DataEvent(this,
Lists.newArrayList(dataItem), eventType));
}
private DataItem getDataItem(MetricDO metricDO) {
MetricResp metricResp = MetricConverter.convert2MetricResp(metricDO,
new HashMap<>(), Lists.newArrayList());
return DataItem.builder().id(metricDO.getId()).name(metricDO.getName())
.bizName(metricDO.getBizName())
.modelId(metricDO.getModelId()).type(TypeEnums.METRIC)
.defaultAgg(metricResp.getDefaultAgg()).build();
}
}

View File

@@ -0,0 +1,75 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.JoinCondition;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelRelaDO;
import com.tencent.supersonic.headless.server.persistence.mapper.ModelRelaDOMapper;
import com.tencent.supersonic.headless.server.service.ModelRelaService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ModelRelaServiceImpl
extends ServiceImpl<ModelRelaDOMapper, ModelRelaDO> implements ModelRelaService {
@Override
public void save(ModelRela modelRela, User user) {
modelRela.createdBy(user.getName());
ModelRelaDO modelRelaDO = convert(modelRela);
save(modelRelaDO);
}
@Override
public void update(ModelRela modelRela, User user) {
modelRela.updatedBy(user.getName());
ModelRelaDO modelRelaDO = convert(modelRela);
updateById(modelRelaDO);
}
@Override
public List<ModelRela> getModelRelaList(Long domainId) {
QueryWrapper<ModelRelaDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ModelRelaDO::getDomainId, domainId);
return list(wrapper).stream().map(this::convert).collect(Collectors.toList());
}
@Override
public List<ModelRela> getModelRela(List<Long> modelIds) {
QueryWrapper<ModelRelaDO> wrapper = new QueryWrapper<>();
if (CollectionUtils.isEmpty(modelIds)) {
return Lists.newArrayList();
}
wrapper.lambda().in(ModelRelaDO::getFromModelId, modelIds).or()
.in(ModelRelaDO::getToModelId, modelIds);
return list(wrapper).stream().map(this::convert).collect(Collectors.toList());
}
@Override
public void delete(Long id) {
removeById(id);
}
private ModelRela convert(ModelRelaDO modelRelaDO) {
ModelRela modelRela = new ModelRela();
BeanMapper.mapper(modelRelaDO, modelRela);
modelRela.setJoinConditions(JSONObject.parseArray(modelRelaDO.getJoinCondition(), JoinCondition.class));
return modelRela;
}
private ModelRelaDO convert(ModelRela modelRelaReq) {
ModelRelaDO modelRelaDO = new ModelRelaDO();
BeanMapper.mapper(modelRelaReq, modelRelaDO);
modelRelaDO.setJoinCondition(JSONObject.toJSONString(modelRelaReq.getJoinConditions()));
return modelRelaDO;
}
}

View File

@@ -0,0 +1,588 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.headless.common.server.pojo.Dim;
import com.tencent.supersonic.headless.common.server.pojo.Identify;
import com.tencent.supersonic.headless.common.server.pojo.ItemDateFilter;
import com.tencent.supersonic.headless.common.server.pojo.Measure;
import com.tencent.supersonic.headless.common.server.pojo.RelateDimension;
import com.tencent.supersonic.headless.common.server.request.DateInfoReq;
import com.tencent.supersonic.headless.common.server.request.DimensionReq;
import com.tencent.supersonic.headless.common.server.request.MetaBatchReq;
import com.tencent.supersonic.headless.common.server.request.MetricReq;
import com.tencent.supersonic.headless.common.server.request.ModelReq;
import com.tencent.supersonic.headless.common.server.request.ModelSchemaFilterReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.common.server.response.DimSchemaResp;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import com.tencent.supersonic.headless.common.server.response.MeasureResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.common.server.response.MetricSchemaResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.common.server.response.ModelSchemaResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DataModelYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.pojo.yaml.MetricYamlTpl;
import com.tencent.supersonic.headless.server.manager.DimensionYamlManager;
import com.tencent.supersonic.headless.server.manager.MetricYamlManager;
import com.tencent.supersonic.headless.server.manager.ModelYamlManager;
import com.tencent.supersonic.headless.server.persistence.dataobject.DateInfoDO;
import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO;
import com.tencent.supersonic.headless.server.persistence.repository.DateInfoRepository;
import com.tencent.supersonic.headless.server.persistence.repository.ModelRepository;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
import com.tencent.supersonic.headless.server.service.DatabaseService;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.DomainService;
import com.tencent.supersonic.headless.server.service.MetricService;
import com.tencent.supersonic.headless.server.service.ModelRelaService;
import com.tencent.supersonic.headless.server.service.ModelService;
import com.tencent.supersonic.headless.server.utils.ModelConverter;
import com.tencent.supersonic.headless.server.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Slf4j
public class ModelServiceImpl implements ModelService {
private ModelRepository modelRepository;
private DatabaseService databaseService;
private DimensionService dimensionService;
private MetricService metricService;
private DomainService domainService;
private ModelRelaService modelRelaService;
private UserService userService;
private DateInfoRepository dateInfoRepository;
public ModelServiceImpl(ModelRepository modelRepository,
DatabaseService databaseService,
@Lazy DimensionService dimensionService,
@Lazy MetricService metricService,
ModelRelaService modelRelaService,
DomainService domainService,
UserService userService,
DateInfoRepository dateInfoRepository) {
this.modelRepository = modelRepository;
this.databaseService = databaseService;
this.dimensionService = dimensionService;
this.metricService = metricService;
this.domainService = domainService;
this.modelRelaService = modelRelaService;
this.userService = userService;
this.dateInfoRepository = dateInfoRepository;
}
@Override
@Transactional
public ModelResp createModel(ModelReq modelReq, User user) throws Exception {
checkName(modelReq);
ModelDO modelDO = ModelConverter.convert(modelReq, user);
modelRepository.createModel(modelDO);
batchCreateDimension(modelDO, user);
batchCreateMetric(modelDO, user);
return ModelConverter.convert(modelDO);
}
@Override
@Transactional
public ModelResp updateModel(ModelReq modelReq, User user) throws Exception {
checkName(modelReq);
ModelDO modelDO = modelRepository.getModelById(modelReq.getId());
int oldStatus = modelDO.getStatus();
ModelConverter.convert(modelDO, modelReq, user);
modelRepository.updateModel(modelDO);
batchCreateDimension(modelDO, user);
batchCreateMetric(modelDO, user);
statusPublish(oldStatus, modelDO);
return ModelConverter.convert(modelDO);
}
private void statusPublish(Integer oldStatus, ModelDO modelDO) {
if (oldStatus.equals(modelDO.getStatus())) {
return;
}
EventType eventType = null;
if (oldStatus.equals(StatusEnum.ONLINE.getCode())
&& modelDO.getStatus().equals(StatusEnum.OFFLINE.getCode())) {
eventType = EventType.DELETE;
} else if (oldStatus.equals(StatusEnum.OFFLINE.getCode())
&& modelDO.getStatus().equals(StatusEnum.ONLINE.getCode())) {
eventType = EventType.ADD;
}
log.info("model:{} status from {} to {}", modelDO.getId(), oldStatus, modelDO.getStatus());
metricService.sendMetricEventBatch(Lists.newArrayList(modelDO.getId()), eventType);
dimensionService.sendDimensionEventBatch(Lists.newArrayList(modelDO.getId()), eventType);
}
@Override
public List<ModelResp> getModelList(ModelFilter modelFilter) {
return ModelConverter.convertList(modelRepository.getModelList(modelFilter));
}
@Override
public Map<Long, ModelResp> getModelMap() {
Map<Long, ModelResp> map = new HashMap<>();
List<ModelResp> modelResps = getModelList(new ModelFilter());
if (CollectionUtils.isEmpty(modelResps)) {
return map;
}
return modelResps.stream().collect(Collectors.toMap(ModelResp::getId, a -> a, (k1, k2) -> k1));
}
@Override
public void deleteModel(Long id, User user) {
ModelDO datasourceDO = modelRepository.getModelById(id);
if (datasourceDO == null) {
return;
}
checkDelete(id);
datasourceDO.setStatus(StatusEnum.DELETED.getCode());
datasourceDO.setUpdatedAt(new Date());
datasourceDO.setUpdatedBy(user.getName());
modelRepository.updateModel(datasourceDO);
}
@Override
public ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric) {
List<DateInfoReq> itemDates = new ArrayList<>();
List<DateInfoDO> dimensions = dateInfoRepository.getDateInfos(dimension);
List<DateInfoDO> metrics = dateInfoRepository.getDateInfos(metric);
log.info("getDateDate, dimension:{}, dimensions dateInfo:{}", dimension, dimensions);
log.info("getDateDate, metric:{}, metrics dateInfo:{}", metric, metrics);
itemDates.addAll(convert(dimensions));
itemDates.addAll(convert(metrics));
ItemDateResp itemDateDescriptor = calculateDateInternal(itemDates);
log.info("itemDateDescriptor:{}", itemDateDescriptor);
return itemDateDescriptor;
}
@Override
public List<MeasureResp> getMeasureListOfModel(List<Long> modelIds) {
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(modelIds);
List<ModelResp> modelResps = getModelList(modelFilter);
return modelResps.stream().flatMap(modelResp -> modelResp.getModelDetail().getMeasures()
.stream().map(measure -> ModelConverter.convert(measure, modelResp))).collect(Collectors.toList());
}
private void batchCreateDimension(ModelDO modelDO, User user) throws Exception {
List<DimensionReq> dimensionReqs = ModelConverter.convertDimensionList(modelDO);
dimensionService.createDimensionBatch(dimensionReqs, user);
}
private void batchCreateMetric(ModelDO datasourceDO, User user) throws Exception {
List<MetricReq> exprMetricReqs = ModelConverter.convertMetricList(datasourceDO);
metricService.createMetricBatch(exprMetricReqs, user);
}
private void checkName(ModelReq modelReq) {
if (NameCheckUtils.containsSpecialCharacters(modelReq.getName())) {
String message = String.format("模型名称[%s]包含特殊字符, 请修改", modelReq.getName());
throw new InvalidArgumentException(message);
}
List<Dim> dims = modelReq.getModelDetail().getDimensions();
List<Measure> measures = modelReq.getModelDetail().getMeasures();
List<Dim> timeDims = modelReq.getTimeDimension();
List<Identify> identifies = modelReq.getModelDetail().getIdentifiers();
if (CollectionUtils.isEmpty(dims)) {
throw new InvalidArgumentException("缺少维度信息");
}
if (!CollectionUtils.isEmpty(measures) && CollectionUtils.isEmpty(timeDims)) {
throw new InvalidArgumentException("有度量时, 不可缺少时间维度");
}
for (Measure measure : measures) {
if (StringUtils.isNotBlank(measure.getName())
&& NameCheckUtils.containsSpecialCharacters(measure.getName())) {
String message = String.format("度量[%s]包含特殊字符, 请修改", measure.getName());
throw new InvalidArgumentException(message);
}
}
for (Dim dim : dims) {
if (StringUtils.isNotBlank(dim.getName())
&& NameCheckUtils.containsSpecialCharacters(dim.getName())) {
String message = String.format("维度[%s]包含特殊字符, 请修改", dim.getName());
throw new InvalidArgumentException(message);
}
}
for (Identify identify : identifies) {
if (StringUtils.isNotBlank(identify.getName())
&& NameCheckUtils.containsSpecialCharacters(identify.getName())) {
String message = String.format("主键/外键[%s]包含特殊字符, 请修改", identify.getName());
throw new InvalidArgumentException(message);
}
}
}
private void checkDelete(Long modelId) {
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
if (!CollectionUtils.isEmpty(metricResps) || !CollectionUtils.isEmpty(dimensionResps)) {
throw new RuntimeException("存在基于该模型创建的指标和维度, 暂不能删除, 请确认");
}
}
private ItemDateResp calculateDateInternal(List<DateInfoReq> itemDates) {
if (CollectionUtils.isEmpty(itemDates)) {
log.warn("itemDates is empty!");
return null;
}
String dateFormat = itemDates.get(0).getDateFormat();
String startDate = itemDates.get(0).getStartDate();
String endDate = itemDates.get(0).getEndDate();
String datePeriod = itemDates.get(0).getDatePeriod();
List<String> unavailableDateList = itemDates.get(0).getUnavailableDateList();
for (DateInfoReq item : itemDates) {
String startDate1 = item.getStartDate();
String endDate1 = item.getEndDate();
List<String> unavailableDateList1 = item.getUnavailableDateList();
if (Strings.isNotEmpty(startDate1) && startDate1.compareTo(startDate) > 0) {
startDate = startDate1;
}
if (Strings.isNotEmpty(endDate1) && endDate1.compareTo(endDate) < 0) {
endDate = endDate1;
}
if (!CollectionUtils.isEmpty(unavailableDateList1)) {
unavailableDateList.addAll(unavailableDateList1);
}
}
return new ItemDateResp(dateFormat, startDate, endDate, datePeriod, unavailableDateList);
}
@Override
public List<ModelResp> getModelListWithAuth(User user, Long domainId, AuthType authType) {
List<ModelResp> modelResps = getModelAuthList(user, authType);
Set<ModelResp> modelRespSet = new HashSet<>(modelResps);
List<ModelResp> modelRespsAuthInheritDomain = getModelRespAuthInheritDomain(user, authType);
modelRespSet.addAll(modelRespsAuthInheritDomain);
if (domainId != null && domainId > 0) {
modelRespSet = modelRespSet.stream().filter(modelResp ->
modelResp.getDomainId().equals(domainId)).collect(Collectors.toSet());
}
return modelRespSet.stream().sorted(Comparator.comparingLong(ModelResp::getId))
.collect(Collectors.toList());
}
public List<ModelResp> getModelRespAuthInheritDomain(User user, AuthType authType) {
Set<DomainResp> domainResps = domainService.getDomainAuthSet(user, authType);
if (CollectionUtils.isEmpty(domainResps)) {
return Lists.newArrayList();
}
List<ModelResp> allModelList = getModelList(new ModelFilter());
Set<Long> domainIds = domainResps.stream().map(DomainResp::getId).collect(Collectors.toSet());
return allModelList.stream().filter(modelResp ->
domainIds.contains(modelResp.getDomainId())).collect(Collectors.toList());
}
@Override
public List<ModelResp> getModelAuthList(User user, AuthType authTypeEnum) {
List<ModelResp> modelResps = getModelList(new ModelFilter());
Set<String> orgIds = userService.getUserAllOrgId(user.getName());
List<ModelResp> modelWithAuth = Lists.newArrayList();
if (authTypeEnum.equals(AuthType.ADMIN)) {
modelWithAuth = modelResps.stream()
.filter(modelResp -> checkAdminPermission(orgIds, user, modelResp))
.collect(Collectors.toList());
}
if (authTypeEnum.equals(AuthType.VISIBLE)) {
modelWithAuth = modelResps.stream()
.filter(domainResp -> checkViewerPermission(orgIds, user, domainResp))
.collect(Collectors.toList());
}
return modelWithAuth;
}
@Override
public List<ModelResp> getModelByDomainIds(List<Long> domainIds) {
if (CollectionUtils.isEmpty(domainIds)) {
return Lists.newArrayList();
}
ModelFilter modelFilter = new ModelFilter();
modelFilter.setDomainIds(domainIds);
List<ModelResp> modelResps = getModelList(modelFilter);
if (CollectionUtils.isEmpty(modelResps)) {
return modelResps;
}
return modelResps.stream().filter(modelResp ->
domainIds.contains(modelResp.getDomainId())).collect(Collectors.toList());
}
@Override
public ModelResp getModel(Long id) {
ModelDO modelDO = getModelDO(id);
if (modelDO == null) {
return null;
}
Map<Long, DomainResp> domainRespMap = domainService.getDomainList().stream()
.collect(Collectors.toMap(DomainResp::getId, d -> d));
return ModelConverter.convert(modelDO, domainRespMap);
}
@Override
public List<String> getModelAdmin(Long id) {
ModelResp modelResp = getModel(id);
if (modelResp == null) {
return Lists.newArrayList();
}
if (!CollectionUtils.isEmpty(modelResp.getAdmins())) {
return modelResp.getAdmins();
}
Long domainId = modelResp.getDomainId();
DomainResp domainResp = domainService.getDomain(domainId);
while (domainResp != null) {
if (!CollectionUtils.isEmpty(domainResp.getAdmins())) {
return domainResp.getAdmins();
}
domainId = domainResp.getParentId();
domainResp = domainService.getDomain(domainId);
}
return Lists.newArrayList();
}
@Override
public ModelSchemaResp fetchSingleModelSchema(Long modelId) {
ModelResp modelResp = getModel(modelId);
ModelSchemaResp modelSchemaResp = new ModelSchemaResp();
BeanUtils.copyProperties(modelResp, modelSchemaResp);
modelSchemaResp.setDimensions(generateDimSchema(modelId));
modelSchemaResp.setMetrics(generateMetricSchema(modelId, modelResp));
return modelSchemaResp;
}
@Override
public List<ModelSchemaResp> fetchModelSchema(ModelSchemaFilterReq modelSchemaFilterReq) {
List<ModelSchemaResp> modelSchemaRespList = new ArrayList<>();
List<Long> modelIds = modelSchemaFilterReq.getModelIds();
if (CollectionUtils.isEmpty(modelIds)) {
modelIds = generateModelIdsReq(modelSchemaFilterReq);
}
MetaFilter metaFilter = new MetaFilter(modelIds);
metaFilter.setStatus(StatusEnum.ONLINE.getCode());
Map<Long, List<MetricResp>> metricRespMap = metricService.getMetrics(metaFilter)
.stream().collect(Collectors.groupingBy(MetricResp::getModelId));
Map<Long, List<DimensionResp>> dimensionRespsMap = dimensionService.getDimensions(metaFilter)
.stream().collect(Collectors.groupingBy(DimensionResp::getModelId));
List<ModelRela> modelRelas = modelRelaService.getModelRela(modelIds);
for (Long modelId : modelIds) {
ModelResp modelResp = getModelMap().get(modelId);
if (modelResp == null || !StatusEnum.ONLINE.getCode().equals(modelResp.getStatus())) {
continue;
}
List<MetricResp> metricResps = metricRespMap.getOrDefault(modelId, Lists.newArrayList());
List<MetricSchemaResp> metricSchemaResps = metricResps.stream().map(metricResp ->
convert(metricResp, modelResp)).collect(Collectors.toList());
List<DimSchemaResp> dimensionResps = dimensionRespsMap.getOrDefault(modelId, Lists.newArrayList())
.stream().map(this::convert).collect(Collectors.toList());
ModelSchemaResp modelSchemaResp = new ModelSchemaResp();
BeanUtils.copyProperties(modelResp, modelSchemaResp);
modelSchemaResp.setDimensions(dimensionResps);
modelSchemaResp.setMetrics(metricSchemaResps);
modelSchemaResp.setModelRelas(modelRelas.stream().filter(modelRela
-> modelRela.getFromModelId().equals(modelId) || modelRela.getToModelId().equals(modelId))
.collect(Collectors.toList()));
modelSchemaRespList.add(modelSchemaResp);
}
return modelSchemaRespList;
}
@Override
public DatabaseResp getDatabaseByModelId(Long modelId) {
ModelResp modelResp = getModel(modelId);
if (modelResp != null) {
Long databaseId = modelResp.getDatabaseId();
return databaseService.getDatabase(databaseId);
}
return null;
}
@Override
public void batchUpdateStatus(MetaBatchReq metaBatchReq, User user) {
if (CollectionUtils.isEmpty(metaBatchReq.getIds())) {
return;
}
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(metaBatchReq.getIds());
List<ModelDO> modelDOS = modelRepository.getModelList(modelFilter);
if (CollectionUtils.isEmpty(modelDOS)) {
return;
}
modelDOS = modelDOS.stream()
.peek(modelDO -> {
modelDO.setStatus(metaBatchReq.getStatus());
modelDO.setUpdatedAt(new Date());
modelDO.setUpdatedBy(user.getName());
})
.collect(Collectors.toList());
modelRepository.batchUpdate(modelDOS);
}
protected ModelDO getModelDO(Long id) {
return modelRepository.getModelById(id);
}
private List<MetricSchemaResp> generateMetricSchema(Long modelId, ModelResp modelResp) {
List<MetricSchemaResp> metricSchemaDescList = new ArrayList<>();
List<MetricResp> metricResps = metricService.getMetrics(new MetaFilter(Lists.newArrayList(modelId)));
metricResps.forEach(metricResp -> metricSchemaDescList.add(convert(metricResp, modelResp)));
return metricSchemaDescList;
}
private List<DimSchemaResp> generateDimSchema(Long modelId) {
List<DimensionResp> dimDescList = dimensionService.getDimensions(new MetaFilter(Lists.newArrayList(modelId)));
return dimDescList.stream().map(this::convert).collect(Collectors.toList());
}
private DimSchemaResp convert(DimensionResp dimensionResp) {
DimSchemaResp dimSchemaResp = new DimSchemaResp();
BeanUtils.copyProperties(dimensionResp, dimSchemaResp);
dimSchemaResp.setUseCnt(0L);
return dimSchemaResp;
}
private MetricSchemaResp convert(MetricResp metricResp, ModelResp modelResp) {
MetricSchemaResp metricSchemaResp = new MetricSchemaResp();
BeanUtils.copyProperties(metricResp, metricSchemaResp);
RelateDimension relateDimension = metricResp.getRelateDimension();
if (relateDimension == null || CollectionUtils.isEmpty(relateDimension.getDrillDownDimensions())) {
metricSchemaResp.setRelateDimension(RelateDimension.builder()
.drillDownDimensions(modelResp.getDrillDownDimensions()).build());
}
metricSchemaResp.setUseCnt(0L);
return metricSchemaResp;
}
private List<DateInfoReq> convert(List<DateInfoDO> dateInfoDOList) {
List<DateInfoReq> dateInfoCommendList = new ArrayList<>();
dateInfoDOList.forEach(dateInfoDO -> {
DateInfoReq dateInfoCommend = new DateInfoReq();
BeanUtils.copyProperties(dateInfoDO, dateInfoCommend);
dateInfoCommend.setUnavailableDateList(JsonUtil.toList(dateInfoDO.getUnavailableDateList(), String.class));
dateInfoCommendList.add(dateInfoCommend);
});
return dateInfoCommendList;
}
private List<Long> generateModelIdsReq(ModelSchemaFilterReq filter) {
if (Objects.nonNull(filter) && !CollectionUtils.isEmpty(filter.getModelIds())) {
return filter.getModelIds();
}
return new ArrayList<>(getModelMap().keySet());
}
public static boolean checkAdminPermission(Set<String> orgIds, User user, ModelResp modelResp) {
List<String> admins = modelResp.getAdmins();
List<String> adminOrgs = modelResp.getAdminOrgs();
if (user.isSuperAdmin()) {
return true;
}
String userName = user.getName();
if (admins.contains(userName) || modelResp.getCreatedBy().equals(userName)) {
return true;
}
if (CollectionUtils.isEmpty(adminOrgs)) {
return false;
}
for (String orgId : orgIds) {
if (adminOrgs.contains(orgId)) {
return true;
}
}
return false;
}
public static boolean checkViewerPermission(Set<String> orgIds, User user, ModelResp modelResp) {
if (checkAdminPermission(orgIds, user, modelResp)) {
return true;
}
List<String> viewers = modelResp.getViewers();
List<String> viewOrgs = modelResp.getViewOrgs();
if (user.isSuperAdmin()) {
return true;
}
if (modelResp.openToAll()) {
return true;
}
String userName = user.getName();
if (viewers.contains(userName) || modelResp.getCreatedBy().equals(userName)) {
return true;
}
if (CollectionUtils.isEmpty(viewOrgs)) {
return false;
}
for (String orgId : orgIds) {
if (viewOrgs.contains(orgId)) {
return true;
}
}
return false;
}
@Override
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName) {
for (Long modelId : modelIds) {
ModelResp modelResp = getModel(modelId);
modelIdName.put(modelId, modelResp.getBizName());
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(modelId));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
metricYamlTplList.addAll(MetricYamlManager.convert2YamlObj(metricResps));
Long databaseId = modelResp.getDatabaseId();
DatabaseResp databaseResp = databaseService.getDatabase(databaseId);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
dataModelYamlTplList.add(ModelYamlManager.convert2YamlObj(modelResp, databaseResp));
if (!dimensionYamlMap.containsKey(modelResp.getBizName())) {
dimensionYamlMap.put(modelResp.getBizName(), new ArrayList<>());
}
List<DimensionResp> dimensionRespList = dimensionResps.stream()
.filter(d -> d.getModelBizName().equalsIgnoreCase(modelResp.getBizName()))
.collect(Collectors.toList());
dimensionYamlMap.get(modelResp.getBizName()).addAll(DimensionYamlManager.convert2DimensionYaml(
dimensionRespList));
}
}
}

View File

@@ -0,0 +1,89 @@
package com.tencent.supersonic.headless.server.service.impl;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.headless.common.server.request.ViewInfoReq;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.common.server.response.ModelSchemaRelaResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.ViewInfoDO;
import com.tencent.supersonic.headless.server.persistence.repository.ViewInfoRepository;
import com.tencent.supersonic.headless.server.pojo.MetaFilter;
import com.tencent.supersonic.headless.server.service.DimensionService;
import com.tencent.supersonic.headless.server.service.MetricService;
import com.tencent.supersonic.headless.server.service.ModelService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Service
public class ViewInfoServiceImpl {
private ViewInfoRepository viewInfoRepository;
private ModelService modelService;
private DimensionService dimensionService;
private MetricService metricService;
public ViewInfoServiceImpl(ViewInfoRepository viewInfoRepository, ModelService modelService,
MetricService metricService, DimensionService dimensionService) {
this.viewInfoRepository = viewInfoRepository;
this.dimensionService = dimensionService;
this.metricService = metricService;
this.modelService = modelService;
}
public List<ViewInfoDO> getViewInfoList(Long domainId) {
return viewInfoRepository.getViewInfoList(domainId);
}
public List<ModelSchemaRelaResp> getDomainSchema(Long domainId, User user) {
List<ModelSchemaRelaResp> domainSchemaRelaResps = Lists.newArrayList();
List<ModelResp> modelResps = modelService.getModelListWithAuth(user, domainId, AuthType.ADMIN);
for (ModelResp modelResp : modelResps) {
ModelSchemaRelaResp domainSchemaRelaResp = new ModelSchemaRelaResp();
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelResp.getId()));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
domainSchemaRelaResp.setModel(modelResp);
domainSchemaRelaResp.setDimensions(dimensionResps);
domainSchemaRelaResp.setMetrics(metricResps);
domainSchemaRelaResp.setDomainId(domainId);
domainSchemaRelaResps.add(domainSchemaRelaResp);
}
return domainSchemaRelaResps;
}
public ViewInfoDO createOrUpdateViewInfo(ViewInfoReq viewInfoReq, User user) {
if (viewInfoReq.getId() == null) {
ViewInfoDO viewInfoDO = new ViewInfoDO();
BeanUtils.copyProperties(viewInfoReq, viewInfoDO);
viewInfoDO.setCreatedAt(new Date());
viewInfoDO.setCreatedBy(user.getName());
viewInfoDO.setUpdatedAt(new Date());
viewInfoDO.setUpdatedBy(user.getName());
viewInfoRepository.createViewInfo(viewInfoDO);
return viewInfoDO;
}
Long id = viewInfoReq.getId();
ViewInfoDO viewInfoDO = viewInfoRepository.getViewInfoById(id);
BeanUtils.copyProperties(viewInfoReq, viewInfoDO);
viewInfoDO.setUpdatedAt(new Date());
viewInfoDO.setUpdatedBy(user.getName());
viewInfoRepository.updateViewInfo(viewInfoDO);
return viewInfoDO;
}
public void deleteViewInfo(Long id) {
viewInfoRepository.deleteViewInfo(id);
}
}

View File

@@ -0,0 +1,64 @@
package com.tencent.supersonic.headless.server.utils;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.headless.common.server.request.DatabaseReq;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.DatabaseDO;
import com.tencent.supersonic.headless.server.pojo.ConnectInfo;
import com.tencent.supersonic.headless.server.pojo.Database;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import java.util.Arrays;
public class DatabaseConverter {
public static Database convert(DatabaseReq databaseReq) {
Database database = new Database();
BeanUtils.copyProperties(databaseReq, database);
ConnectInfo connectInfo = new ConnectInfo();
connectInfo.setUserName(databaseReq.getUsername());
connectInfo.setPassword(databaseReq.getPassword());
connectInfo.setUrl(databaseReq.getConnectUrl());
connectInfo.setDatabase(databaseReq.getDatabase());
database.setConnectInfo(connectInfo);
database.setVersion(databaseReq.getVersion());
return database;
}
public static DatabaseDO convert(Database database, DatabaseDO databaseDO) {
database.setId(databaseDO.getId());
database.setCreatedBy(databaseDO.getCreatedBy());
database.setCreatedAt(databaseDO.getCreatedAt());
BeanUtils.copyProperties(database, databaseDO);
databaseDO.setConfig(JSONObject.toJSONString(database.getConnectInfo()));
databaseDO.setAdmin(String.join(",", database.getAdmins()));
databaseDO.setViewer(String.join(",", database.getViewers()));
return databaseDO;
}
public static DatabaseDO convert(Database database) {
DatabaseDO databaseDO = new DatabaseDO();
BeanUtils.copyProperties(database, databaseDO);
databaseDO.setConfig(JSONObject.toJSONString(database.getConnectInfo()));
databaseDO.setAdmin(String.join(",", database.getAdmins()));
databaseDO.setViewer(String.join(",", database.getViewers()));
return databaseDO;
}
public static DatabaseResp convert(DatabaseDO databaseDO) {
DatabaseResp databaseResp = new DatabaseResp();
BeanUtils.copyProperties(databaseDO, databaseResp);
ConnectInfo connectInfo = JSONObject.parseObject(databaseDO.getConfig(), ConnectInfo.class);
databaseResp.setUrl(connectInfo.getUrl());
databaseResp.setPassword(connectInfo.getPassword());
databaseResp.setUsername(connectInfo.getUserName());
databaseResp.setDatabase(connectInfo.getDatabase());
if (StringUtils.isNotBlank(databaseDO.getAdmin())) {
databaseResp.setAdmins(Arrays.asList(databaseDO.getAdmin().split(",")));
}
if (StringUtils.isNotBlank(databaseDO.getViewer())) {
databaseResp.setViewers(Arrays.asList(databaseDO.getViewer().split(",")));
}
return databaseResp;
}
}

View File

@@ -0,0 +1,87 @@
package com.tencent.supersonic.headless.server.utils;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.common.pojo.enums.DataTypeEnums;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.headless.common.server.pojo.DimValueMap;
import com.tencent.supersonic.headless.common.server.request.DimensionReq;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.ModelResp;
import com.tencent.supersonic.headless.server.pojo.yaml.DimensionYamlTpl;
import com.tencent.supersonic.headless.server.persistence.dataobject.DimensionDO;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class DimensionConverter {
public static DimensionDO convert(DimensionDO dimensionDO, DimensionReq dimensionReq) {
BeanMapper.mapper(dimensionReq, dimensionDO);
if (dimensionReq.getDefaultValues() != null) {
dimensionDO.setDefaultValues(JSONObject.toJSONString(dimensionReq.getDefaultValues()));
}
if (!CollectionUtils.isEmpty(dimensionReq.getDimValueMaps())) {
dimensionDO.setDimValueMaps(JSONObject.toJSONString(dimensionReq.getDimValueMaps()));
} else {
dimensionDO.setDimValueMaps(JSONObject.toJSONString(new ArrayList<>()));
}
if (Objects.nonNull(dimensionReq.getDataType())) {
dimensionDO.setDataType(dimensionReq.getDataType().getType());
}
return dimensionDO;
}
public static DimensionDO convert2DimensionDO(DimensionReq dimensionReq) {
DimensionDO dimensionDO = new DimensionDO();
BeanMapper.mapper(dimensionReq, dimensionDO);
if (dimensionReq.getDefaultValues() != null) {
dimensionDO.setDefaultValues(JSONObject.toJSONString(dimensionReq.getDefaultValues()));
}
if (dimensionReq.getDimValueMaps() != null) {
dimensionDO.setDimValueMaps(JSONObject.toJSONString(dimensionReq.getDimValueMaps()));
}
if (Objects.nonNull(dimensionReq.getDataType())) {
dimensionDO.setDataType(dimensionReq.getDataType().getType());
}
dimensionDO.setStatus(StatusEnum.ONLINE.getCode());
return dimensionDO;
}
public static DimensionResp convert2DimensionResp(DimensionDO dimensionDO,
Map<Long, ModelResp> modelRespMap) {
DimensionResp dimensionResp = new DimensionResp();
BeanUtils.copyProperties(dimensionDO, dimensionResp);
dimensionResp.setModelName(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getName());
dimensionResp.setModelBizName(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getBizName());
if (dimensionDO.getDefaultValues() != null) {
dimensionResp.setDefaultValues(JSONObject.parseObject(dimensionDO.getDefaultValues(), List.class));
}
dimensionResp.setModelFilterSql(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getFilterSql());
if (Strings.isNotEmpty(dimensionDO.getDimValueMaps())) {
dimensionResp.setDimValueMaps(JsonUtil.toList(dimensionDO.getDimValueMaps(), DimValueMap.class));
}
if (Strings.isNotEmpty(dimensionDO.getDataType())) {
dimensionResp.setDataType(DataTypeEnums.of(dimensionDO.getDataType()));
}
return dimensionResp;
}
public static DimensionYamlTpl convert2DimensionYamlTpl(DimensionResp dimension) {
DimensionYamlTpl dimensionYamlTpl = new DimensionYamlTpl();
BeanUtils.copyProperties(dimension, dimensionYamlTpl);
dimensionYamlTpl.setName(dimension.getBizName());
dimensionYamlTpl.setOwners(dimension.getCreatedBy());
return dimensionYamlTpl;
}
}

View File

@@ -0,0 +1,55 @@
package com.tencent.supersonic.headless.server.utils;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.headless.common.server.request.DomainReq;
import com.tencent.supersonic.headless.common.server.response.DimensionResp;
import com.tencent.supersonic.headless.common.server.response.DomainResp;
import com.tencent.supersonic.headless.common.server.response.MetricResp;
import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class DomainConvert {
public static DomainDO convert(DomainReq domainReq, User user) {
DomainDO domainDO = new DomainDO();
domainReq.createdBy(user.getName());
BeanUtils.copyProperties(domainReq, domainDO);
domainDO.setAdmin(String.join(",", domainReq.getAdmins()));
domainDO.setAdminOrg(String.join(",", domainReq.getAdminOrgs()));
domainDO.setViewer(String.join(",", domainReq.getViewers()));
domainDO.setViewOrg(String.join(",", domainReq.getViewOrgs()));
return domainDO;
}
public static DomainResp convert(DomainDO domainDO, Map<Long, String> domainFullPathMap) {
DomainResp domainResp = new DomainResp();
BeanUtils.copyProperties(domainDO, domainResp);
domainResp.setFullPath(domainFullPathMap.get(domainDO.getId()));
domainResp.setAdmins(StringUtils.isBlank(domainDO.getAdmin())
? Lists.newArrayList() : Arrays.asList(domainDO.getAdmin().split(",")));
domainResp.setAdminOrgs(StringUtils.isBlank(domainDO.getAdminOrg())
? Lists.newArrayList() : Arrays.asList(domainDO.getAdminOrg().split(",")));
domainResp.setViewers(StringUtils.isBlank(domainDO.getViewer())
? Lists.newArrayList() : Arrays.asList(domainDO.getViewer().split(",")));
domainResp.setViewOrgs(StringUtils.isBlank(domainDO.getViewOrg())
? Lists.newArrayList() : Arrays.asList(domainDO.getViewOrg().split(",")));
return domainResp;
}
public static DomainResp convert(DomainDO domainDO, Map<Long, String> domainFullPathMap,
Map<Long, List<DimensionResp>> dimensionMap,
Map<Long, List<MetricResp>> metricMap) {
DomainResp domainResp = convert(domainDO, domainFullPathMap);
domainResp.setDimensionCnt(dimensionMap.getOrDefault(domainResp.getId(), Lists.newArrayList()).size());
domainResp.setMetricCnt(metricMap.getOrDefault(domainResp.getId(), Lists.newArrayList()).size());
return domainResp;
}
}

View File

@@ -0,0 +1,198 @@
package com.tencent.supersonic.headless.server.utils;
import static com.tencent.supersonic.common.pojo.Constants.AT_SYMBOL;
import static com.tencent.supersonic.common.pojo.Constants.COLON;
import static com.tencent.supersonic.common.pojo.Constants.DOUBLE_SLASH;
import static com.tencent.supersonic.common.pojo.Constants.EMPTY;
import static com.tencent.supersonic.common.pojo.Constants.JDBC_PREFIX_FORMATTER;
import static com.tencent.supersonic.common.pojo.Constants.NEW_LINE_CHAR;
import static com.tencent.supersonic.common.pojo.Constants.PATTERN_JDBC_TYPE;
import static com.tencent.supersonic.common.pojo.Constants.SPACE;
import com.alibaba.druid.util.StringUtils;
import com.tencent.supersonic.headless.common.server.enums.DataType;
import com.tencent.supersonic.headless.common.server.response.DatabaseResp;
import com.tencent.supersonic.common.util.MD5Util;
import com.tencent.supersonic.headless.server.pojo.Database;
import com.tencent.supersonic.headless.server.pojo.JdbcDataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import javax.sql.DataSource;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class JdbcDataSourceUtils {
@Getter
private static Set releaseSourceSet = new HashSet();
private JdbcDataSource jdbcDataSource;
public JdbcDataSourceUtils(JdbcDataSource jdbcDataSource) {
this.jdbcDataSource = jdbcDataSource;
}
public static boolean testDatabase(Database database) {
try {
Class.forName(getDriverClassName(database.getConnectInfo().getUrl()));
} catch (ClassNotFoundException e) {
log.error(e.toString(), e);
return false;
}
try (Connection con = DriverManager.getConnection(database.getConnectInfo().getUrl(),
database.getConnectInfo().getUserName(), database.getConnectInfo().getPassword());) {
return con != null;
} catch (SQLException e) {
log.error(e.toString(), e);
}
return false;
}
public static void releaseConnection(Connection connection) {
if (null != connection) {
try {
connection.close();
} catch (Exception e) {
log.error("Connection release error", e);
}
}
}
public static void closeResult(ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
log.error("ResultSet close error", e);
}
}
}
public static String isSupportedDatasource(String jdbcUrl) {
String dataSourceName = getDataSourceName(jdbcUrl);
if (StringUtils.isEmpty(dataSourceName)) {
throw new RuntimeException("Not supported dataSource: jdbcUrl=" + jdbcUrl);
}
if (!DataType.getAllSupportedDatasourceNameSet().contains(dataSourceName)) {
throw new RuntimeException("Not supported dataSource: jdbcUrl=" + jdbcUrl);
}
String urlPrefix = String.format(JDBC_PREFIX_FORMATTER, dataSourceName);
String checkUrl = jdbcUrl.replaceFirst(DOUBLE_SLASH, EMPTY).replaceFirst(AT_SYMBOL, EMPTY);
if (urlPrefix.equals(checkUrl)) {
throw new RuntimeException("Communications link failure");
}
return dataSourceName;
}
public static String getDataSourceName(String jdbcUrl) {
String dataSourceName = null;
jdbcUrl = jdbcUrl.replaceAll(NEW_LINE_CHAR, EMPTY).replaceAll(SPACE, EMPTY).trim();
Matcher matcher = PATTERN_JDBC_TYPE.matcher(jdbcUrl);
if (matcher.find()) {
dataSourceName = matcher.group().split(COLON)[1];
}
return dataSourceName;
}
public static String getDriverClassName(String jdbcUrl) {
String className = null;
try {
className = DriverManager.getDriver(jdbcUrl.trim()).getClass().getName();
} catch (SQLException e) {
log.error("e", e);
}
if (!StringUtils.isEmpty(className) && !className.contains("com.sun.proxy")
&& !className.contains("net.sf.cglib.proxy")) {
return className;
}
DataType dataTypeEnum = DataType.urlOf(jdbcUrl);
if (dataTypeEnum != null) {
return dataTypeEnum.getDriver();
}
throw new RuntimeException("Not supported data type: jdbcUrl=" + jdbcUrl);
}
public static String getKey(String name, String jdbcUrl, String username, String password, String version,
boolean isExt) {
StringBuilder sb = new StringBuilder();
sb.append(StringUtils.isEmpty(name) ? "null" : name).append(COLON);
sb.append(StringUtils.isEmpty(username) ? "null" : username).append(COLON);
sb.append(StringUtils.isEmpty(password) ? "null" : password).append(COLON);
sb.append(jdbcUrl.trim()).append(COLON);
if (isExt && !StringUtils.isEmpty(version)) {
sb.append(version);
} else {
sb.append("null");
}
return MD5Util.getMD5(sb.toString(), true, 64);
}
public DataSource getDataSource(DatabaseResp databaseResp) throws RuntimeException {
return jdbcDataSource.getDataSource(databaseResp);
}
public Connection getConnection(DatabaseResp databaseResp) throws RuntimeException {
Connection conn = getConnectionWithRetry(databaseResp);
if (conn == null) {
try {
releaseDataSource(databaseResp);
DataSource dataSource = getDataSource(databaseResp);
return dataSource.getConnection();
} catch (Exception e) {
log.error("Get connection error, jdbcUrl:{}, e:{}", databaseResp.getUrl(), e);
throw new RuntimeException("Get connection error, jdbcUrl:" + databaseResp.getUrl()
+ " you can try again later or reset datasource");
}
}
return conn;
}
private Connection getConnectionWithRetry(DatabaseResp databaseResp) {
int rc = 1;
for (; ; ) {
if (rc > 3) {
return null;
}
try {
Connection connection = getDataSource(databaseResp).getConnection();
if (connection != null && connection.isValid(5)) {
return connection;
}
} catch (Exception e) {
log.error("e", e);
}
try {
Thread.sleep((long) Math.pow(2, rc) * 1000);
} catch (InterruptedException e) {
log.error("e", e);
}
rc++;
}
}
public void releaseDataSource(DatabaseResp databaseResp) {
jdbcDataSource.removeDatasource(databaseResp);
}
}

Some files were not shown because too many files have changed in this diff Show More