45 changed files with 2632 additions and 0 deletions
@ -0,0 +1,95 @@ |
|||||
|
package io.sc.engine.rule.core.code.impl.support.processor; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import io.sc.engine.rule.core.po.model.Parameter; |
||||
|
import io.sc.engine.rule.core.po.model.processor.DecisionTableParameterProcessor; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
import io.sc.engine.rule.core.util.JacksonObjectMapper; |
||||
|
|
||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
|
||||
|
public class DecisionTable { |
||||
|
public static List<Map<String,Object>> parse(String json) throws Exception{ |
||||
|
return JacksonObjectMapper.getDefaultObjectMapper().readValue(json, new TypeReference<List<Map<String,Object>>>(){}); |
||||
|
} |
||||
|
|
||||
|
public static String generateGroovyCode(Parameter parameter,DecisionTableParameterProcessor processor) throws Exception{ |
||||
|
if(parameter==null || processor==null){ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
List<Map<String,Object>> decisionTables =parse(processor.getDecisionTable()); |
||||
|
if(decisionTables!=null && decisionTables.size()>0) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
int conditionRowCount =getConditionRowCount(decisionTables); |
||||
|
int resultRowCount =getResultRowCount(decisionTables); |
||||
|
int colCount =getColCount(decisionTables); |
||||
|
sb.append("if (1==2){").append("\n"); |
||||
|
sb.append("\t\t}"); |
||||
|
for(int j=1;j<colCount;j++) {//一列一列生成
|
||||
|
sb.append("else if (true"); |
||||
|
for(int i=0;i<conditionRowCount;i++) { |
||||
|
String condition =decisionTables.get(i).get("C"+j)==null?"":decisionTables.get(i).get("C"+j).toString(); |
||||
|
if("Y".equalsIgnoreCase(condition) || "T".equalsIgnoreCase(condition)) { |
||||
|
sb.append(" && ").append("(").append(ExpressionReplacer.groovy((String)decisionTables.get(i).get("C0"),null)).append(")"); |
||||
|
} |
||||
|
} |
||||
|
sb.append("){").append("\n"); |
||||
|
for(int l=conditionRowCount;l<(conditionRowCount+resultRowCount);l++) { |
||||
|
sb.append("\t\t\t").append(ExpressionReplacer.groovy((String)decisionTables.get(l).get("C0"),null)).append(" ="); |
||||
|
String expression =(String)decisionTables.get(l).get("C"+j); |
||||
|
sb.append(ExpressionReplacer.groovy(expression, parameter.getValueType())); |
||||
|
sb.append(";"); |
||||
|
sb.append("\n"); |
||||
|
} |
||||
|
sb.append("\t\t}"); |
||||
|
} |
||||
|
return sb.toString(); |
||||
|
} |
||||
|
}catch(Exception e) { |
||||
|
throw new RuntimeException("There was a Error when generate " + parameter.getName()+ "'s DecisionTable groovy source code.", e); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static int getColCount(List<Map<String,Object>> decisionTables) { |
||||
|
if(decisionTables!=null && decisionTables.size()>0) { |
||||
|
Map<String,Object> row =decisionTables.get(0); |
||||
|
if(row!=null && row.size()>0) { |
||||
|
int index =0; |
||||
|
while(row.containsKey("C"+index)) { |
||||
|
index++; |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int getConditionRowCount(List<Map<String,Object>> decisionTables) { |
||||
|
if(decisionTables!=null && decisionTables.size()>0) { |
||||
|
int index =0; |
||||
|
while("condition".equalsIgnoreCase((String)decisionTables.get(index).get("type"))) { |
||||
|
index++; |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int getResultRowCount(List<Map<String,Object>> decisionTables) { |
||||
|
if(decisionTables!=null && decisionTables.size()>0) { |
||||
|
int index =0; |
||||
|
for(Map<String,Object> map : decisionTables) { |
||||
|
if("result".equalsIgnoreCase((String)map.get("type"))) { |
||||
|
index++; |
||||
|
} |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
package io.sc.engine.rule.core.code.impl.support.processor; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import io.sc.engine.rule.core.po.model.Parameter; |
||||
|
import io.sc.engine.rule.core.po.model.processor.DecisionTable2CParameterProcessor; |
||||
|
import io.sc.engine.rule.core.util.CodeReplacer; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
import io.sc.engine.rule.core.util.JacksonObjectMapper; |
||||
|
|
||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||
|
|
||||
|
public class DecisionTable2C { |
||||
|
public static List<Map<String,Object>> parse(String json) throws Exception{ |
||||
|
return JacksonObjectMapper.getDefaultObjectMapper().readValue(json, new TypeReference<List<Map<String,Object>>>(){}); |
||||
|
} |
||||
|
|
||||
|
public static String generateGroovyCode(Parameter parameter,DecisionTable2CParameterProcessor processor) throws Exception{ |
||||
|
if(parameter==null || processor==null){ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
List<Map<String,Object>> decisionTable2Cs =parse(processor.getDecisionTable2C()); |
||||
|
if(decisionTable2Cs!=null && decisionTable2Cs.size()>0) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
int rowCount =decisionTable2Cs.size(); |
||||
|
int colCount =getColCount(decisionTable2Cs); |
||||
|
sb.append("if (1==2){").append("\n"); |
||||
|
sb.append("\t\t}"); |
||||
|
for(int i=1;i<rowCount;i++) { |
||||
|
for(int j=1;j<colCount;j++) { |
||||
|
sb.append("else if ("); |
||||
|
sb.append("(").append(ExpressionReplacer.groovy((String)decisionTable2Cs.get(i).get("C0"),null)).append(") && (").append(ExpressionReplacer.groovy((String)decisionTable2Cs.get(0).get("C"+j),null)).append(")"); |
||||
|
sb.append("){").append("\n"); |
||||
|
Object obj =decisionTable2Cs.get(i).get("C"+j); |
||||
|
if(obj!=null) { |
||||
|
sb.append("\t\t\t").append(ExpressionReplacer.ARGUMENT_NAME).append(".").append(CodeReplacer.fieldName(parameter.getCode())).append(" ="); |
||||
|
String expression =obj.toString(); |
||||
|
sb.append(ExpressionReplacer.groovy(expression, parameter.getValueType())).append(";\n"); |
||||
|
} |
||||
|
sb.append("\t\t}"); |
||||
|
} |
||||
|
} |
||||
|
return sb.toString(); |
||||
|
} |
||||
|
}catch(Exception e) { |
||||
|
throw new RuntimeException("There was a Error when generate " + parameter.getName()+ "'s DecisionTable2C groovy source code.", e); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static int getColCount(List<Map<String,Object>> decisionTable2Cs) { |
||||
|
if(decisionTable2Cs!=null && decisionTable2Cs.size()>0) { |
||||
|
Map<String,Object> row =decisionTable2Cs.get(0); |
||||
|
if(row!=null && row.size()>0) { |
||||
|
int index =0; |
||||
|
while(row.containsKey("C"+index)) { |
||||
|
index++; |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
} |
@ -0,0 +1,195 @@ |
|||||
|
package io.sc.engine.rule.core.code.impl.support.processor; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValueType; |
||||
|
import io.sc.engine.rule.core.mxgraph.parser.DecisionTreeParser; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ConditionNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.EdgeNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ExpressionNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.GraphNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ResourceAbstractNode; |
||||
|
import io.sc.engine.rule.core.po.model.Parameter; |
||||
|
import io.sc.engine.rule.core.po.model.processor.DecisionTreeParameterProcessor; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
|
||||
|
public class DecisionTree { |
||||
|
public static GraphNode parse(String json) throws Exception{ |
||||
|
if(json!=null && json.trim().length()>1) { |
||||
|
DecisionTreeParser parser =new DecisionTreeParser(); |
||||
|
GraphNode result =parser.parse(json); |
||||
|
return result; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
/** |
||||
|
* 生成决策树 groovy 代码 |
||||
|
* @param parameter 参数 |
||||
|
* @param processor 参数处理器 |
||||
|
* @return groovy 代码 |
||||
|
* @throws Exception 违例 |
||||
|
*/ |
||||
|
public static String generateGroovyCode(Parameter parameter,DecisionTreeParameterProcessor processor) throws Exception{ |
||||
|
try { |
||||
|
Map<String,String> methodNameCache =new HashMap<String,String>(); |
||||
|
GraphNode node =parse(processor.getDecisionTree()); |
||||
|
return _generateGroovyCode(methodNameCache,parameter,node); |
||||
|
}catch(Exception e) { |
||||
|
throw new RuntimeException("There was a Error when generate " + parameter.getName()+ "'s DecisionTree groovy source code.", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成决策树 groovy 代码 |
||||
|
* @param methodNameCache 方法名缓存,用于在生成 groovy 代码时,去除重复的方法名,通常会发生在多条边指向同一个节点时,该节点产生的方法会出现多次 |
||||
|
* @param parameter 参数 |
||||
|
* @param node 决策树第一个有效节点(即第一个条件节点) |
||||
|
* @return groovy 代码 |
||||
|
*/ |
||||
|
private static String _generateGroovyCode(Map<String,String> methodNameCache,Parameter parameter,GraphNode node) { |
||||
|
if(node!=null) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
String methodName ="Tree_" + parameter.getCode() + "_" + node.getId(); |
||||
|
if(node instanceof ConditionNode) { |
||||
|
ConditionNode conditionNode =(ConditionNode)node; |
||||
|
if(!methodNameCache.containsKey(methodName)) { |
||||
|
sb.append(generateConditionGroovyCode(methodNameCache,parameter,conditionNode,methodName)); |
||||
|
methodNameCache.put(methodName, null); |
||||
|
} |
||||
|
}else if(node instanceof ExpressionNode) { |
||||
|
ExpressionNode expressionNode =(ExpressionNode)node; |
||||
|
if(!methodNameCache.containsKey(methodName)) { |
||||
|
sb.append(generateExpressionGroovyCode(methodNameCache,parameter,expressionNode,methodName)); |
||||
|
methodNameCache.put(methodName, null); |
||||
|
} |
||||
|
}else if(node instanceof ResourceAbstractNode) { |
||||
|
ResourceAbstractNode modelAbstractNode =(ResourceAbstractNode)node; |
||||
|
if(!methodNameCache.containsKey(methodName)) { |
||||
|
sb.append(generateResourceAbstractGroovyCode(methodNameCache,parameter,modelAbstractNode,methodName)); |
||||
|
methodNameCache.put(methodName, null); |
||||
|
} |
||||
|
} |
||||
|
return sb.toString(); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成决策树条件节点 groovy 代码 |
||||
|
* @param methodNameCache 方法名缓存 |
||||
|
* @param parameter 参数 |
||||
|
* @param conditionNode 条件节点 |
||||
|
* @param methodName 方法名 |
||||
|
* @param returnType 返回值类型 |
||||
|
* @return groovy 代码 |
||||
|
*/ |
||||
|
private static String generateConditionGroovyCode(Map<String,String> methodNameCache,Parameter parameter,ConditionNode conditionNode,String methodName) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
sb.append("\tprivate static ").append(parameter.getValueType()).append(" ").append(methodName).append("(Executor executor,Argument ").append(ExpressionReplacer.ARGUMENT_NAME).append("){//条件判断").append("\n"); |
||||
|
List<GraphNode> branches =conditionNode.getOuts(); //获取条件的所有出口边
|
||||
|
if(branches!=null && branches.size()>0) { |
||||
|
List<GraphNode> outs =orderEdges(branches); //对出口边进行排序,有条件的放前面,无条件的放后面
|
||||
|
for(int i=0;i<outs.size();i++) { |
||||
|
EdgeNode edge =(EdgeNode)outs.get(i); //出口边
|
||||
|
GraphNode nexNode =edge.getOuts().get(0); //出口边指向的节点
|
||||
|
|
||||
|
if(i==0) { |
||||
|
sb.append("\t\tif((").append(ExpressionReplacer.groovy(conditionNode.getCondition(),null)).append(")==").append(ExpressionReplacer.groovy(edge.getValue(),edge.getValueType())).append("){").append("\n"); |
||||
|
}else { |
||||
|
if(edge.getValue()!=null && !edge.getValue().trim().isEmpty()) { |
||||
|
sb.append("else if((").append(ExpressionReplacer.groovy(conditionNode.getCondition(),null)).append(")==").append(ExpressionReplacer.groovy(edge.getValue(),edge.getValueType())).append("){").append("\n"); |
||||
|
}else { |
||||
|
sb.append("else {").append("\n"); |
||||
|
} |
||||
|
} |
||||
|
String commands =edge.getCommands(); |
||||
|
if(commands!=null && !"".equals(commands.trim())) { |
||||
|
String[] commandSplits =commands.split("\n"); |
||||
|
if(commandSplits!=null && commandSplits.length>0) { |
||||
|
for(String split : commandSplits) { |
||||
|
sb.append("\t\t\t").append(split).append("\n"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
sb.append("\t\t\t").append("return Tree_").append(parameter.getCode()).append("_").append(nexNode.getId()).append("(").append("executor,").append(ExpressionReplacer.ARGUMENT_NAME).append(");").append("\n"); |
||||
|
sb.append("\t\t}"); |
||||
|
} |
||||
|
sb.append("\n\t}\n\n"); |
||||
|
//继续生成后续方法
|
||||
|
for(GraphNode out :outs) { |
||||
|
sb.append(_generateGroovyCode(methodNameCache,parameter,out.getOuts().get(0))); |
||||
|
} |
||||
|
} |
||||
|
return sb.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成决策树表达式节点 groovy 代码 |
||||
|
* @param methodNameCache 方法名缓存 |
||||
|
* @param parameter 参数 |
||||
|
* @param expressionNode 表达式节点 |
||||
|
* @param methodName 方法名 |
||||
|
* @param returnType 返回值类型 |
||||
|
* @return 代码 |
||||
|
*/ |
||||
|
private static String generateExpressionGroovyCode(Map<String,String> methodNameCache,Parameter parameter,ExpressionNode expressionNode,String methodName) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
sb.append("\tprivate static ").append(parameter.getValueType()).append(" ").append(methodName).append("(Executor executor,Argument ").append(ExpressionReplacer.ARGUMENT_NAME).append("){//表达式").append("\n"); |
||||
|
String expression =expressionNode.getExpression(); |
||||
|
String commands =expressionNode.getCommands(); |
||||
|
if(commands!=null && !commands.isEmpty()) { |
||||
|
sb.append("\t\t").append(ExpressionReplacer.groovy(commands,null)).append("\n"); |
||||
|
} |
||||
|
sb.append("\t\t").append("return ").append(ExpressionReplacer.groovy(expression,parameter.getValueType())).append(";\n"); |
||||
|
sb.append("\t}").append("\n\n"); |
||||
|
|
||||
|
return sb.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成决策树模型摘要节点 groovy 代码 |
||||
|
* @param methodNameCache 方法名缓存 |
||||
|
* @param parameter 参数 |
||||
|
* @param expressionNode 表达式节点 |
||||
|
* @param methodName 方法名 |
||||
|
* @param returnType 返回值类型 |
||||
|
* @return 代码 |
||||
|
*/ |
||||
|
private static String generateResourceAbstractGroovyCode(Map<String,String> methodNameCache,Parameter parameter,ResourceAbstractNode expressionNode,String methodName) { |
||||
|
StringBuilder sb =new StringBuilder(); |
||||
|
sb.append("\tprivate static ").append(ValueType.getSimpleJavaType(parameter.getValueType())).append(" ").append(methodName).append("(Executor executor,Argument ").append(ExpressionReplacer.ARGUMENT_NAME).append("){//资源").append("\n"); |
||||
|
String code =ExpressionReplacer.groovy(expressionNode.getCode(),ValueType.String.getJavaType()); |
||||
|
String version =ExpressionReplacer.groovy(expressionNode.getVersion(),ValueType.Long.getJavaType()); |
||||
|
if(version==null || version.trim().isEmpty()) { |
||||
|
version ="null"; |
||||
|
} |
||||
|
sb.append("\t\t").append("return new ").append(ValueType.getSimpleJavaType(parameter.getValueType())).append("(").append(code).append(",").append(version).append(")").append(";\n"); |
||||
|
sb.append("\t}").append("\n\n"); |
||||
|
|
||||
|
return sb.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 对条件边进行排序,将有条件值的排在前面,无条件值的放在后面,以便生成 groovy 代码时,将无条件值的转为 else 语句 |
||||
|
* @param nodes 条件边 |
||||
|
* @return 排序后的条件边 |
||||
|
*/ |
||||
|
private static List<GraphNode> orderEdges(List<GraphNode> nodes){ |
||||
|
List<GraphNode> result =new ArrayList<GraphNode>(); |
||||
|
for(GraphNode node : nodes) { |
||||
|
if(node instanceof EdgeNode) { |
||||
|
EdgeNode edge =(EdgeNode)node; |
||||
|
String value =edge.getValue(); |
||||
|
if(value!=null && !"".equals(value.trim())) { |
||||
|
result.add(0, edge); |
||||
|
}else { |
||||
|
result.add(edge); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
package io.sc.engine.rule.core.convert.converter; |
||||
|
|
||||
|
import org.springframework.core.convert.ConversionService; |
||||
|
import org.springframework.core.convert.converter.ConverterRegistry; |
||||
|
import org.springframework.core.convert.support.GenericConversionService; |
||||
|
import io.sc.engine.rule.core.convert.support.JsonStringToObjectConverterFactory; |
||||
|
import io.sc.engine.rule.core.convert.support.MapToObjectConverterFactory; |
||||
|
import io.sc.engine.rule.core.convert.support.NumberToNumberConverterFactory; |
||||
|
import io.sc.engine.rule.core.convert.support.ObjectToStringConverter; |
||||
|
import io.sc.engine.rule.core.convert.support.StringToBooleanConverter; |
||||
|
import io.sc.engine.rule.core.convert.support.StringToDateConverter; |
||||
|
import io.sc.engine.rule.core.convert.support.StringToNumberConverterFactory; |
||||
|
|
||||
|
public class DataTypeConversionService extends GenericConversionService { |
||||
|
private static volatile DataTypeConversionService sharedInstance; |
||||
|
|
||||
|
public DataTypeConversionService() { |
||||
|
addDefaultConverters(this); |
||||
|
} |
||||
|
|
||||
|
public static ConversionService getSharedInstance() { |
||||
|
DataTypeConversionService cs = sharedInstance; |
||||
|
if (cs == null) { |
||||
|
synchronized (DataTypeConversionService.class) { |
||||
|
cs = sharedInstance; |
||||
|
if (cs == null) { |
||||
|
cs = new DataTypeConversionService(); |
||||
|
sharedInstance = cs; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return cs; |
||||
|
} |
||||
|
|
||||
|
public static void addDefaultConverters(ConverterRegistry converterRegistry) { |
||||
|
converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());//数字-->数字
|
||||
|
converterRegistry.addConverterFactory(new MapToObjectConverterFactory()); //Map<String,Object>-->Object
|
||||
|
converterRegistry.addConverter(new StringToDateConverter());//字符串-->日期
|
||||
|
converterRegistry.addConverter(new ObjectToStringConverter());//对象-->字符串
|
||||
|
converterRegistry.addConverter(new StringToBooleanConverter());//字符串-->布尔
|
||||
|
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());//字符串-->数字
|
||||
|
converterRegistry.addConverterFactory(new JsonStringToObjectConverterFactory());//json字符串-->对象
|
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package io.sc.engine.rule.core.enums; |
||||
|
|
||||
|
/** |
||||
|
* 流程定义状态 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public enum DeployStatus { |
||||
|
HISTORY, //历史
|
||||
|
ON_LINE, //上线
|
||||
|
OFF_LINE, //下线
|
||||
|
SKETCH, //草稿
|
||||
|
APPROVING //审批中
|
||||
|
} |
@ -0,0 +1,38 @@ |
|||||
|
package io.sc.engine.rule.core.function; |
||||
|
|
||||
|
import java.util.Date; |
||||
|
|
||||
|
import io.sc.engine.rule.core.util.DateUtil; |
||||
|
|
||||
|
/** |
||||
|
* 日期函数 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public class DateFunction { |
||||
|
/** |
||||
|
* 获取当前日期 |
||||
|
* @return 当前日期 |
||||
|
*/ |
||||
|
public static Date now() { |
||||
|
return new Date(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 格式化日期 |
||||
|
* @param date 日期 |
||||
|
* @return 格式化后的日期字符串 |
||||
|
*/ |
||||
|
public static String yyyyMMdd(Date date) { |
||||
|
return DateUtil.formatDate(date, DateUtil.yyyyMMdd); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 格式化日期 |
||||
|
* @param date 日期 |
||||
|
* @return 格式化后的日期字符串 |
||||
|
*/ |
||||
|
public static String yyyy_MM_dd(Date date) { |
||||
|
return DateUtil.formatDate(date, DateUtil.yyyy_MM_dd); |
||||
|
} |
||||
|
} |
@ -0,0 +1,163 @@ |
|||||
|
package io.sc.engine.rule.core.mxgraph.parser; |
||||
|
|
||||
|
import java.awt.Color; |
||||
|
import java.awt.image.BufferedImage; |
||||
|
import java.io.IOException; |
||||
|
import java.io.OutputStream; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
import javax.imageio.ImageIO; |
||||
|
|
||||
|
import org.w3c.dom.Document; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ConditionNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.EdgeNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ExpressionNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.GraphNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.ResourceAbstractNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.po.StartNode; |
||||
|
import io.sc.engine.rule.core.mxgraph.support.DecisionTreeMxGraph; |
||||
|
|
||||
|
import com.mxgraph.io.mxCodec; |
||||
|
import com.mxgraph.model.mxCell; |
||||
|
import com.mxgraph.model.mxGraphModel; |
||||
|
import com.mxgraph.model.mxICell; |
||||
|
import com.mxgraph.util.mxCellRenderer; |
||||
|
import com.mxgraph.util.mxConstants; |
||||
|
import com.mxgraph.util.mxXmlUtils; |
||||
|
import com.mxgraph.view.mxGraph; |
||||
|
|
||||
|
/** |
||||
|
* 决策树解析器 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public class DecisionTreeParser { |
||||
|
/** |
||||
|
* 将 xml 解析成决策树对象,返回第一个有效节点 |
||||
|
* 使用者可通过该节点遍历整个决策树 |
||||
|
* @param xml mxgraph xml |
||||
|
* @return 决策树第一个有效节点 |
||||
|
*/ |
||||
|
public GraphNode parse(String xml) { |
||||
|
Map<String,GraphNode> nodes =parseNodes(xml); |
||||
|
return buildAndGetFirstEffectiveNode(nodes); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 生成图片 |
||||
|
* @param xml mxgraph xml |
||||
|
* @param outputStream 输出流 |
||||
|
* @param format 图片格式 |
||||
|
* @throws IOException 违例 |
||||
|
*/ |
||||
|
public void generateImage(String xml,OutputStream outputStream,String format) throws IOException { |
||||
|
Document doc = mxXmlUtils.parseXml(xml); |
||||
|
mxCodec codec = new mxCodec(doc); |
||||
|
mxGraphModel model =(mxGraphModel)codec.decode(doc.getDocumentElement()); |
||||
|
mxGraph graph = new DecisionTreeMxGraph(model); |
||||
|
graph.setHtmlLabels(true); |
||||
|
|
||||
|
//设置默认样式
|
||||
|
Map<String, Object> style = graph.getStylesheet().getDefaultVertexStyle(); |
||||
|
style.put(mxConstants.STYLE_GRADIENTCOLOR, "#FFFFFF"); |
||||
|
style.put(mxConstants.STYLE_ROUNDED, true); |
||||
|
style.put(mxConstants.STYLE_SHADOW, true); |
||||
|
|
||||
|
BufferedImage image = mxCellRenderer.createBufferedImage(graph, null,1, Color.WHITE, true, null); |
||||
|
if(image!=null) { |
||||
|
ImageIO.write(image, format, outputStream); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Map<String,GraphNode> parseNodes(String xml){ |
||||
|
Document doc = mxXmlUtils.parseXml(xml); |
||||
|
mxCodec codec = new mxCodec(doc); |
||||
|
mxGraphModel model =(mxGraphModel)codec.decode(doc.getDocumentElement()); |
||||
|
mxCell root =(mxCell)model.getRoot(); //获取根(<root> 标签对应的节点)
|
||||
|
mxICell container =root.getChildAt(0);//.getChildAt(0); //获取包含自定义图形的容器
|
||||
|
Map<String,GraphNode> result =new HashMap<String,GraphNode>(); |
||||
|
int childCount =container.getChildCount(); |
||||
|
for(int i=0;i<childCount;i++) { |
||||
|
mxCell cell =(mxCell)container.getChildAt(i); |
||||
|
String id =cell.getId(); |
||||
|
String label =cell.getAttribute("label"); |
||||
|
String type =cell.getAttribute("type"); |
||||
|
if(GraphNode.START.equalsIgnoreCase(type)) { |
||||
|
StartNode node =new StartNode(); |
||||
|
node.setId(id); |
||||
|
node.setLabel(label); |
||||
|
result.put(id, node); |
||||
|
}else if(GraphNode.CONDITION.equalsIgnoreCase(type)) { |
||||
|
ConditionNode node =new ConditionNode(); |
||||
|
node.setId(id); |
||||
|
node.setLabel(label); |
||||
|
node.setCondition(cell.getAttribute("condition")); |
||||
|
result.put(id, node); |
||||
|
}else if(GraphNode.EXPRESSION.equalsIgnoreCase(type)) { |
||||
|
ExpressionNode node =new ExpressionNode(); |
||||
|
node.setId(id); |
||||
|
node.setLabel(label); |
||||
|
node.setExpression(cell.getAttribute("expression")); |
||||
|
node.setCommands(cell.getAttribute("commands")); |
||||
|
result.put(id, node); |
||||
|
}else if(GraphNode.RESOURCE_ABSTRACT.equalsIgnoreCase(type)) { |
||||
|
ResourceAbstractNode node =new ResourceAbstractNode(); |
||||
|
node.setId(id); |
||||
|
node.setLabel(label); |
||||
|
node.setCode(cell.getAttribute("code")); |
||||
|
node.setVersion(cell.getAttribute("version")); |
||||
|
result.put(id, node); |
||||
|
}else if(GraphNode.EDGE.equalsIgnoreCase(type)) { |
||||
|
EdgeNode node =new EdgeNode(); |
||||
|
node.setId(id); |
||||
|
node.setLabel(label); |
||||
|
node.setValueType(cell.getAttribute("valueType")); |
||||
|
node.setValue(cell.getAttribute("value")); |
||||
|
node.setCommands(cell.getAttribute("commands")); |
||||
|
mxICell source =cell.getSource(); |
||||
|
if(source!=null) { |
||||
|
node.setSourceId(source.getId()); |
||||
|
} |
||||
|
mxICell target =cell.getTarget(); |
||||
|
if(target!=null) { |
||||
|
node.setTargetId(target.getId()); |
||||
|
} |
||||
|
result.put(id, node); |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private GraphNode buildAndGetFirstEffectiveNode(Map<String,GraphNode> nodes) { |
||||
|
StartNode startNode =null; |
||||
|
for(String id : nodes.keySet()) { |
||||
|
GraphNode node =nodes.get(id); |
||||
|
if(node instanceof StartNode) { |
||||
|
startNode =(StartNode)node; |
||||
|
}else if(node instanceof EdgeNode) { |
||||
|
EdgeNode edgeNode =(EdgeNode)node; |
||||
|
String sourceId =edgeNode.getSourceId(); |
||||
|
String targetId =edgeNode.getTargetId(); |
||||
|
GraphNode source =nodes.get(sourceId); |
||||
|
GraphNode target =nodes.get(targetId); |
||||
|
if(source!=null) { |
||||
|
source.addOut(edgeNode); |
||||
|
edgeNode.addOut(target); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if(startNode!=null) { |
||||
|
List<GraphNode> edges =startNode.getOuts(); |
||||
|
if(edges!=null && edges.size()>0) { |
||||
|
GraphNode edge =edges.get(0); |
||||
|
List<GraphNode> outs =edge.getOuts(); |
||||
|
if(outs!=null && outs.size()>0) { |
||||
|
return outs.get(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package io.sc.engine.rule.core.mxgraph.po; |
||||
|
|
||||
|
public class ConfigurableResourceAbstractNode extends GraphNode{ |
||||
|
private String code; //代码
|
||||
|
private String version; //版本
|
||||
|
private String inputCommands; //输入指令集
|
||||
|
private String outputCommands; //输出指令集
|
||||
|
|
||||
|
public String getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
public void setCode(String code) { |
||||
|
this.code = code; |
||||
|
} |
||||
|
public String getVersion() { |
||||
|
return version; |
||||
|
} |
||||
|
public void setVersion(String version) { |
||||
|
this.version = version; |
||||
|
} |
||||
|
public String getInputCommands() { |
||||
|
return inputCommands; |
||||
|
} |
||||
|
public void setInputCommands(String inputCommands) { |
||||
|
this.inputCommands = inputCommands; |
||||
|
} |
||||
|
public String getOutputCommands() { |
||||
|
return outputCommands; |
||||
|
} |
||||
|
public void setOutputCommands(String outputCommands) { |
||||
|
this.outputCommands = outputCommands; |
||||
|
} |
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "ConfigurableResourceAbstractNode [id=" + id |
||||
|
+ ", label=" + label |
||||
|
+ ", code=" + code |
||||
|
+ ", version=" + version |
||||
|
+ ", inputCommands=" + inputCommands |
||||
|
+ ", outputCommands=" + outputCommands |
||||
|
+ ", outs=" + outs + "]"; |
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
package io.sc.engine.rule.core.mxgraph.support; |
||||
|
|
||||
|
import org.w3c.dom.Element; |
||||
|
|
||||
|
import com.mxgraph.model.mxCell; |
||||
|
import com.mxgraph.model.mxIGraphModel; |
||||
|
import com.mxgraph.view.mxGraph; |
||||
|
import com.mxgraph.view.mxStylesheet; |
||||
|
|
||||
|
/** |
||||
|
* 自定义决策树 mxGraph 类 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public class DecisionTreeMxGraph extends mxGraph { |
||||
|
public DecisionTreeMxGraph() { |
||||
|
super(); |
||||
|
} |
||||
|
|
||||
|
public DecisionTreeMxGraph(mxIGraphModel model, mxStylesheet stylesheet) { |
||||
|
super(model, stylesheet); |
||||
|
} |
||||
|
|
||||
|
public DecisionTreeMxGraph(mxIGraphModel model) { |
||||
|
super(model); |
||||
|
} |
||||
|
|
||||
|
public DecisionTreeMxGraph(mxStylesheet stylesheet) { |
||||
|
super(stylesheet); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
|
||||
|
/** |
||||
|
* 覆盖默认实现 |
||||
|
* 用于获取 User Object 节点的 label |
||||
|
*/ |
||||
|
public String convertValueToString(Object cell) { |
||||
|
if(cell==null) { |
||||
|
return null; |
||||
|
} |
||||
|
if(cell instanceof mxCell) { |
||||
|
mxCell _cell =(mxCell)cell; |
||||
|
Object value =_cell.getValue(); |
||||
|
if(value!=null) { |
||||
|
if(value instanceof Element) { |
||||
|
Element element =(Element)value; |
||||
|
String label =element.getAttribute("label"); |
||||
|
return HtmlUtil.text(label); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return super.convertValueToString(cell); |
||||
|
} |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
package io.sc.engine.rule.core.po.dictionary; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo; |
||||
|
|
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type",defaultImpl=FolderDictionary.class) |
||||
|
@JsonSubTypes({ |
||||
|
@JsonSubTypes.Type(value=FolderDictionary.class), |
||||
|
@JsonSubTypes.Type(value=JavaClassDictionary.class), |
||||
|
@JsonSubTypes.Type(value=UserDefinedJavaClassDictionary.class), |
||||
|
@JsonSubTypes.Type(value=EnumDictionary.class) |
||||
|
}) |
||||
|
public abstract class Dictionary { |
||||
|
protected String id; //Id
|
||||
|
protected String code; //代码
|
||||
|
protected String name; //名称
|
||||
|
protected String description; //描述
|
||||
|
protected Integer order; //排序
|
||||
|
private List<Dictionary> children =new ArrayList<Dictionary>();//孩子集合
|
||||
|
|
||||
|
public Dictionary() {} |
||||
|
public Dictionary(String id) { |
||||
|
this.id =id; |
||||
|
} |
||||
|
|
||||
|
public String getId() { |
||||
|
return id; |
||||
|
} |
||||
|
public void setId(String id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
public String getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
public void setCode(String code) { |
||||
|
this.code = code; |
||||
|
} |
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
public String getDescription() { |
||||
|
return description; |
||||
|
} |
||||
|
public void setDescription(String description) { |
||||
|
this.description = description; |
||||
|
} |
||||
|
public Integer getOrder() { |
||||
|
return order; |
||||
|
} |
||||
|
public void setOrder(Integer order) { |
||||
|
this.order = order; |
||||
|
} |
||||
|
public List<Dictionary> getChildren() { |
||||
|
return children; |
||||
|
} |
||||
|
public void setChildren(List<Dictionary> children) { |
||||
|
this.children = children; |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package io.sc.engine.rule.core.po.lib.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.core.po.lib.RangeIndicatorValidator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DATE_RANGE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DateRangeIndicatorValidator extends RangeIndicatorValidator { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DATE_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package io.sc.engine.rule.core.po.lib.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.core.po.lib.RangeIndicatorValidator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DECIMAL_RANGE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DecimalRangeIndicatorValidator extends RangeIndicatorValidator { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DECIMAL_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.parameter; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ParameterType; |
||||
|
import io.sc.engine.rule.core.po.model.Parameter; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数(常量) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("CONSTANT") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class ConstantParameter extends Parameter{ |
||||
|
@Override |
||||
|
public ParameterType getType() { |
||||
|
return ParameterType.CONSTANT; |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.po.model.ParameterProcessor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(简单决策表) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DECISION_TABLE_2C") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DecisionTable2CParameterProcessor extends ParameterProcessor { |
||||
|
private String decisionTable2C;//简单决策表
|
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE_2C; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable2C() { |
||||
|
return decisionTable2C; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable2C(String decisionTable2C) { |
||||
|
this.decisionTable2C = decisionTable2C; |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.po.model.ParameterProcessor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策表) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DECISION_TABLE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DecisionTableParameterProcessor extends ParameterProcessor { |
||||
|
private String decisionTable;//决策表
|
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable() { |
||||
|
return decisionTable; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable(String decisionTable) { |
||||
|
this.decisionTable = decisionTable; |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.po.model.ParameterProcessor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策树) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DECISION_TREE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DecisionTreeParameterProcessor extends ParameterProcessor { |
||||
|
private String decisionTree;//决策树
|
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TREE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTree() { |
||||
|
return decisionTree; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTree(String decisionTree) { |
||||
|
this.decisionTree = decisionTree; |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.po.model.RangeParameterValidator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DATE_RANGE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DateRangeParameterValidator extends RangeParameterValidator { |
||||
|
|
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
package io.sc.engine.rule.core.po.model.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.po.model.RangeParameterValidator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; |
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围) |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
@JsonTypeName("DECIMAL_RANGE") |
||||
|
@JsonIgnoreProperties(ignoreUnknown=true) |
||||
|
public class DecimalRangeParameterValidator extends RangeParameterValidator { |
||||
|
|
||||
|
} |
@ -0,0 +1,22 @@ |
|||||
|
package io.sc.engine.rule.core.util; |
||||
|
|
||||
|
import org.springframework.core.convert.ConversionService; |
||||
|
import io.sc.engine.rule.core.convert.converter.DataTypeConversionService; |
||||
|
|
||||
|
/** |
||||
|
* 数据类型转换器 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public class DataTypeConvertor { |
||||
|
private static ConversionService service =DataTypeConversionService.getSharedInstance(); |
||||
|
|
||||
|
public static Object convert(Object value,Class<?> targetClass) throws Exception{ |
||||
|
if(value!=null){ |
||||
|
if(!value.getClass().equals(targetClass)){ |
||||
|
value =service.convert(value, targetClass); |
||||
|
} |
||||
|
} |
||||
|
return value; |
||||
|
} |
||||
|
} |
@ -0,0 +1,235 @@ |
|||||
|
package io.sc.engine.rule.core.util; |
||||
|
|
||||
|
import java.text.DateFormat; |
||||
|
import java.text.DateFormatSymbols; |
||||
|
import java.text.ParseException; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.Calendar; |
||||
|
import java.util.Date; |
||||
|
import java.util.Locale; |
||||
|
|
||||
|
/** |
||||
|
* 日期工具类 |
||||
|
* @author wangshaoping |
||||
|
* |
||||
|
*/ |
||||
|
public class DateUtil { |
||||
|
public static final String GMT ="EEE dd MMM yyyy HH:mm:ss z"; |
||||
|
public static final String GMT_COMMA ="EEE, dd MMM yyyy HH:mm:ss z"; |
||||
|
|
||||
|
public static final String GMT_CHINESE =GMT; |
||||
|
public static final String GMT_CHINESE_COMMA =GMT_COMMA; |
||||
|
|
||||
|
public static final String ISO_8601 ="yyyy-MM-dd'T'HH:mm:ssz"; |
||||
|
public static final String yyyy_MM_dd_T_HH_mm_ss ="yyyy-MM-dd'T'HH:mm:ss"; |
||||
|
public static final String yyyy_MM_dd_HH_mm_ss_SSS ="yyyy-MM-dd HH:mm:ss.SSS"; |
||||
|
public static final String yyyy_MM_dd_HH_mm_ss ="yyyy-MM-dd HH:mm:ss"; |
||||
|
public static final String yyyy_MM_dd_HH_mm ="yyyy-MM-dd HH:mm"; |
||||
|
public static final String yyyy_MM_dd_HH ="yyyy-MM-dd HH"; |
||||
|
public static final String yyyy_MM_dd ="yyyy-MM-dd"; |
||||
|
|
||||
|
public static final String yyyyMMdd ="yyyyMMdd"; |
||||
|
|
||||
|
public static final String HH_mm_ss ="HH:mm:ss"; |
||||
|
public static final String HH_mm_ss_SSS ="HH:mm:ss.SSS"; |
||||
|
|
||||
|
public static final String FILE_yyyy_MM_dd_HH_mm_ss ="yyyy-MM-dd_HH_mm_ss"; |
||||
|
public static final String FILE_yyyy_MM_dd ="yyyy-MM-dd"; |
||||
|
|
||||
|
public static final String yyyy_MM_dd_HH_mm_ss_fffffffff ="yyyy-MM-dd hh:mm:ss.fffffffff"; |
||||
|
|
||||
|
private static final String[] WEEKDAYS = {"", "一", "二", "三", "四", "五", "六", "日"}; |
||||
|
private static final String[] MONTHS = {"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"}; |
||||
|
private static final String[] AMPM = {"上午", "下午"}; |
||||
|
private static final String[] SUPPORTED_DATE_FORMAT =new String[]{ |
||||
|
GMT_CHINESE_COMMA, |
||||
|
GMT_CHINESE, |
||||
|
GMT_COMMA, |
||||
|
GMT, |
||||
|
ISO_8601, |
||||
|
yyyy_MM_dd_HH_mm_ss_SSS, |
||||
|
yyyy_MM_dd_HH_mm_ss, |
||||
|
yyyy_MM_dd_HH_mm, |
||||
|
yyyy_MM_dd_HH, |
||||
|
yyyy_MM_dd, |
||||
|
yyyyMMdd |
||||
|
}; |
||||
|
private static final String SUPPORTED_DATE_FORMAT_EXCEPTION_MESSAGE ="unsupported date format, the valiate format include : \n" |
||||
|
+ GMT_CHINESE_COMMA + "\n" |
||||
|
+ GMT_CHINESE + "\n" |
||||
|
+ GMT_COMMA + "\n" |
||||
|
+ GMT + "\n" |
||||
|
+ ISO_8601 + "\n" |
||||
|
+ yyyy_MM_dd_HH_mm_ss + "\n" |
||||
|
+ yyyy_MM_dd_HH_mm + "\n" |
||||
|
+ yyyy_MM_dd_HH + "\n" |
||||
|
+ yyyy_MM_dd + "\n" |
||||
|
+ yyyyMMdd + "\n"; |
||||
|
|
||||
|
/** |
||||
|
* 获取日期格式化对象 |
||||
|
* @param format 日期格式化字符串 |
||||
|
* @return 日期格式化对象 |
||||
|
*/ |
||||
|
public static DateFormat getDateFormat(String format){ |
||||
|
if(format==null || "".equals(format)){ |
||||
|
return null; |
||||
|
} |
||||
|
if(GMT.equals(format) || GMT_COMMA.equals(format)){ |
||||
|
return new SimpleDateFormat(format,Locale.US); |
||||
|
}else if(GMT_CHINESE.equals(format) || GMT_CHINESE_COMMA.equals(format)){ |
||||
|
DateFormatSymbols sym = new DateFormatSymbols(Locale.CHINA); |
||||
|
sym.setAmPmStrings(AMPM); |
||||
|
sym.setShortWeekdays(WEEKDAYS); |
||||
|
sym.setWeekdays(WEEKDAYS); |
||||
|
sym.setMonths(MONTHS); |
||||
|
return new SimpleDateFormat(format); |
||||
|
}else{ |
||||
|
return new SimpleDateFormat(format); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 解析日期字符串,格式 yyyy-MM-dd HH:mm:ss |
||||
|
* @param str 日期字符串 |
||||
|
* @return 日期 |
||||
|
*/ |
||||
|
public static Date parseDate(String str) { |
||||
|
try { |
||||
|
return parseDate(str,DateUtil.yyyy_MM_dd_HH_mm_ss); |
||||
|
} catch (ParseException e) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 解析日期字符串 |
||||
|
* @param str 日期字符串 |
||||
|
* @param format 日期格式字符串 |
||||
|
* @return 日期 |
||||
|
* @throws ParseException 违例 |
||||
|
*/ |
||||
|
public static Date parseDate(String str, String format) throws ParseException{ |
||||
|
if(str!=null || !"".equals(str)){ |
||||
|
DateFormat df =getDateFormat(format); |
||||
|
if(df!=null){ |
||||
|
return df.parse(str); |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 采用支持的日期格式尝试解析 |
||||
|
* 只要其中一个能够成功解析则返回解析后的日期,否则抛出违例 |
||||
|
* @param str 日期字符串 |
||||
|
* @return 日期 |
||||
|
* @throws ParseException 违例 |
||||
|
*/ |
||||
|
public static Date tryParseDate(String str) throws ParseException{ |
||||
|
if(str==null || "".equals(str)){ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
for(String format : SUPPORTED_DATE_FORMAT){ |
||||
|
try { |
||||
|
return parseDate(str,format); |
||||
|
} catch (ParseException e) { |
||||
|
} |
||||
|
} |
||||
|
throw new ParseException(SUPPORTED_DATE_FORMAT_EXCEPTION_MESSAGE,0); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 采用支持的日期格式尝试解析 |
||||
|
* 只要其中一个能够成功解析则返回解析后的日期,否则抛出违例 |
||||
|
* @param strs 日期字符串数组 |
||||
|
* @return 日期数组 |
||||
|
* @throws ParseException 违例 |
||||
|
*/ |
||||
|
public static Date[] tryParseDates(String[] strs) throws ParseException{ |
||||
|
if(strs==null){ |
||||
|
return null; |
||||
|
} |
||||
|
if(strs.length==0){ |
||||
|
return new Date[0]; |
||||
|
} |
||||
|
Date[] result =new Date[strs.length]; |
||||
|
for(int i=0;i<strs.length;i++){ |
||||
|
result[i] =tryParseDate(strs[i]); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 格式化日期对象 |
||||
|
* @param date 日期对象 |
||||
|
* @param format 日期格式 |
||||
|
* @return 日期字符串 |
||||
|
*/ |
||||
|
public static String formatDate(Date date, String format){ |
||||
|
if(date!=null){ |
||||
|
DateFormat df =getDateFormat(format); |
||||
|
if(df!=null){ |
||||
|
return df.format(date); |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 日期加一天 |
||||
|
* @param date 日期 |
||||
|
* @return 加一天后的日期 |
||||
|
*/ |
||||
|
public static Date addOneDay(Date date){ |
||||
|
if(date==null){ |
||||
|
return null; |
||||
|
} |
||||
|
Calendar c =Calendar.getInstance(); |
||||
|
c.setTime(date); |
||||
|
c.add(Calendar.DATE, 1); |
||||
|
return c.getTime(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 日期减一天 |
||||
|
* @param date 日期 |
||||
|
* @return 减一天后的日期 |
||||
|
*/ |
||||
|
public static Date subOneDay(Date date){ |
||||
|
if(date==null){ |
||||
|
return null; |
||||
|
} |
||||
|
Calendar c =Calendar.getInstance(); |
||||
|
c.setTime(date); |
||||
|
c.add(Calendar.DATE, -1); |
||||
|
return c.getTime(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 清除日期中的时间部分 |
||||
|
* @param date 日期 |
||||
|
* @return 清除日期中的时间部分的日期 |
||||
|
*/ |
||||
|
public static Date cleanTime(Date date){ |
||||
|
if(date==null){ |
||||
|
return null; |
||||
|
} |
||||
|
Calendar c =Calendar.getInstance(); |
||||
|
c.setTime(date); |
||||
|
c.set(Calendar.HOUR_OF_DAY, 0); |
||||
|
c.set(Calendar.MINUTE, 0); |
||||
|
c.set(Calendar.SECOND, 0); |
||||
|
return c.getTime(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 将 java.lang.Date 对象转换成 java.sql.Date 对象 |
||||
|
* @param date java.lang.Date 对象转换成 |
||||
|
* @return java.sql.Date 对象 |
||||
|
*/ |
||||
|
public static java.sql.Date toSqlDate(Date date){ |
||||
|
return new java.sql.Date(date.getTime()); |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
// 在浏览器 window 对象中新建名为 APP 的容器变量, 用于存放平台的全局变量
|
||||
|
window.APP = {}; |
||||
|
// 全局配置
|
||||
|
window.APP.configure ={ |
||||
|
// 应用上下文路径
|
||||
|
webContextPath: '[(@{/})]'.startsWith('[')? '/' : '[(@{/})]', |
||||
|
// 默认后端 API 请求的服务地址前缀
|
||||
|
apiContextPaths: { |
||||
|
DEFAULT: '[(@{/})]'.startsWith('[')? 'http://localhost:8080/' : '[(@{/})]', |
||||
|
}, |
||||
|
// 是否启用本地 mock
|
||||
|
enableLocalMock : false, |
||||
|
// mock 请求响应时间(单位:毫秒)
|
||||
|
localMockTimeout : 10, |
||||
|
// 是否启用使用远程服务端配置
|
||||
|
enableRemoteConfigure : true, |
||||
|
// 是否首先使用本地路由
|
||||
|
useLocaleRouterFirst : true, |
||||
|
// axios 配置
|
||||
|
axios : { |
||||
|
baseURL: '', |
||||
|
timeout: 1000 * 60, |
||||
|
crossdomain: true, |
||||
|
basicAuth: { |
||||
|
enable: true, |
||||
|
username: 'admin', |
||||
|
password: 'admin', |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,539 @@ |
|||||
|
/* Logo 字体 */ |
||||
|
@font-face { |
||||
|
font-family: "iconfont logo"; |
||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); |
||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); |
||||
|
} |
||||
|
|
||||
|
.logo { |
||||
|
font-family: "iconfont logo"; |
||||
|
font-size: 160px; |
||||
|
font-style: normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
|
||||
|
/* tabs */ |
||||
|
.nav-tabs { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.nav-tabs .nav-more { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
height: 42px; |
||||
|
line-height: 42px; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
#tabs { |
||||
|
border-bottom: 1px solid #eee; |
||||
|
} |
||||
|
|
||||
|
#tabs li { |
||||
|
cursor: pointer; |
||||
|
width: 100px; |
||||
|
height: 40px; |
||||
|
line-height: 40px; |
||||
|
text-align: center; |
||||
|
font-size: 16px; |
||||
|
border-bottom: 2px solid transparent; |
||||
|
position: relative; |
||||
|
z-index: 1; |
||||
|
margin-bottom: -1px; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#tabs .active { |
||||
|
border-bottom-color: #f00; |
||||
|
color: #222; |
||||
|
} |
||||
|
|
||||
|
.tab-container .content { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* 页面布局 */ |
||||
|
.main { |
||||
|
padding: 30px 100px; |
||||
|
width: 960px; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
|
||||
|
.main .logo { |
||||
|
color: #333; |
||||
|
text-align: left; |
||||
|
margin-bottom: 30px; |
||||
|
line-height: 1; |
||||
|
height: 110px; |
||||
|
margin-top: -50px; |
||||
|
overflow: hidden; |
||||
|
*zoom: 1; |
||||
|
} |
||||
|
|
||||
|
.main .logo a { |
||||
|
font-size: 160px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.helps { |
||||
|
margin-top: 40px; |
||||
|
} |
||||
|
|
||||
|
.helps pre { |
||||
|
padding: 20px; |
||||
|
margin: 10px 0; |
||||
|
border: solid 1px #e7e1cd; |
||||
|
background-color: #fffdef; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
.icon_lists { |
||||
|
width: 100% !important; |
||||
|
overflow: hidden; |
||||
|
*zoom: 1; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li { |
||||
|
width: 100px; |
||||
|
margin-bottom: 10px; |
||||
|
margin-right: 20px; |
||||
|
text-align: center; |
||||
|
list-style: none !important; |
||||
|
cursor: default; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li .code-name { |
||||
|
line-height: 1.2; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .icon { |
||||
|
display: block; |
||||
|
height: 100px; |
||||
|
line-height: 100px; |
||||
|
font-size: 42px; |
||||
|
margin: 10px auto; |
||||
|
color: #333; |
||||
|
-webkit-transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
-moz-transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .icon:hover { |
||||
|
font-size: 100px; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .svg-icon { |
||||
|
/* 通过设置 font-size 来改变图标大小 */ |
||||
|
width: 1em; |
||||
|
/* 图标和文字相邻时,垂直对齐 */ |
||||
|
vertical-align: -0.15em; |
||||
|
/* 通过设置 color 来改变 SVG 的颜色/fill */ |
||||
|
fill: currentColor; |
||||
|
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 |
||||
|
normalize.css 中也包含这行 */ |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li .name, |
||||
|
.icon_lists li .code-name { |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
/* markdown 样式 */ |
||||
|
.markdown { |
||||
|
color: #666; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.8; |
||||
|
} |
||||
|
|
||||
|
.highlight { |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.markdown img { |
||||
|
vertical-align: middle; |
||||
|
max-width: 100%; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
color: #404040; |
||||
|
font-weight: 500; |
||||
|
line-height: 40px; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2, |
||||
|
.markdown h3, |
||||
|
.markdown h4, |
||||
|
.markdown h5, |
||||
|
.markdown h6 { |
||||
|
color: #404040; |
||||
|
margin: 1.6em 0 0.6em 0; |
||||
|
font-weight: 500; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
font-size: 28px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2 { |
||||
|
font-size: 22px; |
||||
|
} |
||||
|
|
||||
|
.markdown h3 { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.markdown h4 { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.markdown h5 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown h6 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown hr { |
||||
|
height: 1px; |
||||
|
border: 0; |
||||
|
background: #e9e9e9; |
||||
|
margin: 16px 0; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown p { |
||||
|
margin: 1em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown>p, |
||||
|
.markdown>blockquote, |
||||
|
.markdown>.highlight, |
||||
|
.markdown>ol, |
||||
|
.markdown>ul { |
||||
|
width: 80%; |
||||
|
} |
||||
|
|
||||
|
.markdown ul>li { |
||||
|
list-style: circle; |
||||
|
} |
||||
|
|
||||
|
.markdown>ul li, |
||||
|
.markdown blockquote ul>li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown>ul li p, |
||||
|
.markdown>ol li p { |
||||
|
margin: 0.6em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown ol>li { |
||||
|
list-style: decimal; |
||||
|
} |
||||
|
|
||||
|
.markdown>ol li, |
||||
|
.markdown blockquote ol>li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown code { |
||||
|
margin: 0 3px; |
||||
|
padding: 0 5px; |
||||
|
background: #eee; |
||||
|
border-radius: 3px; |
||||
|
} |
||||
|
|
||||
|
.markdown strong, |
||||
|
.markdown b { |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.markdown>table { |
||||
|
border-collapse: collapse; |
||||
|
border-spacing: 0px; |
||||
|
empty-cells: show; |
||||
|
border: 1px solid #e9e9e9; |
||||
|
width: 95%; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th { |
||||
|
white-space: nowrap; |
||||
|
color: #333; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th, |
||||
|
.markdown>table td { |
||||
|
border: 1px solid #e9e9e9; |
||||
|
padding: 8px 16px; |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th { |
||||
|
background: #F7F7F7; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote { |
||||
|
font-size: 90%; |
||||
|
color: #999; |
||||
|
border-left: 4px solid #e9e9e9; |
||||
|
padding-left: 0.8em; |
||||
|
margin: 1em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote p { |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.markdown .anchor { |
||||
|
opacity: 0; |
||||
|
transition: opacity 0.3s ease; |
||||
|
margin-left: 8px; |
||||
|
} |
||||
|
|
||||
|
.markdown .waiting { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
|
||||
|
.markdown h1:hover .anchor, |
||||
|
.markdown h2:hover .anchor, |
||||
|
.markdown h3:hover .anchor, |
||||
|
.markdown h4:hover .anchor, |
||||
|
.markdown h5:hover .anchor, |
||||
|
.markdown h6:hover .anchor { |
||||
|
opacity: 1; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.markdown>br, |
||||
|
.markdown>p>br { |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.hljs { |
||||
|
display: block; |
||||
|
background: white; |
||||
|
padding: 0.5em; |
||||
|
color: #333333; |
||||
|
overflow-x: auto; |
||||
|
} |
||||
|
|
||||
|
.hljs-comment, |
||||
|
.hljs-meta { |
||||
|
color: #969896; |
||||
|
} |
||||
|
|
||||
|
.hljs-string, |
||||
|
.hljs-variable, |
||||
|
.hljs-template-variable, |
||||
|
.hljs-strong, |
||||
|
.hljs-emphasis, |
||||
|
.hljs-quote { |
||||
|
color: #df5000; |
||||
|
} |
||||
|
|
||||
|
.hljs-keyword, |
||||
|
.hljs-selector-tag, |
||||
|
.hljs-type { |
||||
|
color: #a71d5d; |
||||
|
} |
||||
|
|
||||
|
.hljs-literal, |
||||
|
.hljs-symbol, |
||||
|
.hljs-bullet, |
||||
|
.hljs-attribute { |
||||
|
color: #0086b3; |
||||
|
} |
||||
|
|
||||
|
.hljs-section, |
||||
|
.hljs-name { |
||||
|
color: #63a35c; |
||||
|
} |
||||
|
|
||||
|
.hljs-tag { |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.hljs-title, |
||||
|
.hljs-attr, |
||||
|
.hljs-selector-id, |
||||
|
.hljs-selector-class, |
||||
|
.hljs-selector-attr, |
||||
|
.hljs-selector-pseudo { |
||||
|
color: #795da3; |
||||
|
} |
||||
|
|
||||
|
.hljs-addition { |
||||
|
color: #55a532; |
||||
|
background-color: #eaffea; |
||||
|
} |
||||
|
|
||||
|
.hljs-deletion { |
||||
|
color: #bd2c00; |
||||
|
background-color: #ffecec; |
||||
|
} |
||||
|
|
||||
|
.hljs-link { |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
|
||||
|
/* 代码高亮 */ |
||||
|
/* PrismJS 1.15.0 |
||||
|
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ |
||||
|
/** |
||||
|
* prism.js default theme for JavaScript, CSS and HTML |
||||
|
* Based on dabblet (http://dabblet.com) |
||||
|
* @author Lea Verou |
||||
|
*/ |
||||
|
code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
color: black; |
||||
|
background: none; |
||||
|
text-shadow: 0 1px white; |
||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; |
||||
|
text-align: left; |
||||
|
white-space: pre; |
||||
|
word-spacing: normal; |
||||
|
word-break: normal; |
||||
|
word-wrap: normal; |
||||
|
line-height: 1.5; |
||||
|
|
||||
|
-moz-tab-size: 4; |
||||
|
-o-tab-size: 4; |
||||
|
tab-size: 4; |
||||
|
|
||||
|
-webkit-hyphens: none; |
||||
|
-moz-hyphens: none; |
||||
|
-ms-hyphens: none; |
||||
|
hyphens: none; |
||||
|
} |
||||
|
|
||||
|
pre[class*="language-"]::-moz-selection, |
||||
|
pre[class*="language-"] ::-moz-selection, |
||||
|
code[class*="language-"]::-moz-selection, |
||||
|
code[class*="language-"] ::-moz-selection { |
||||
|
text-shadow: none; |
||||
|
background: #b3d4fc; |
||||
|
} |
||||
|
|
||||
|
pre[class*="language-"]::selection, |
||||
|
pre[class*="language-"] ::selection, |
||||
|
code[class*="language-"]::selection, |
||||
|
code[class*="language-"] ::selection { |
||||
|
text-shadow: none; |
||||
|
background: #b3d4fc; |
||||
|
} |
||||
|
|
||||
|
@media print { |
||||
|
|
||||
|
code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
text-shadow: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Code blocks */ |
||||
|
pre[class*="language-"] { |
||||
|
padding: 1em; |
||||
|
margin: .5em 0; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
:not(pre)>code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
background: #f5f2f0; |
||||
|
} |
||||
|
|
||||
|
/* Inline code */ |
||||
|
:not(pre)>code[class*="language-"] { |
||||
|
padding: .1em; |
||||
|
border-radius: .3em; |
||||
|
white-space: normal; |
||||
|
} |
||||
|
|
||||
|
.token.comment, |
||||
|
.token.prolog, |
||||
|
.token.doctype, |
||||
|
.token.cdata { |
||||
|
color: slategray; |
||||
|
} |
||||
|
|
||||
|
.token.punctuation { |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.namespace { |
||||
|
opacity: .7; |
||||
|
} |
||||
|
|
||||
|
.token.property, |
||||
|
.token.tag, |
||||
|
.token.boolean, |
||||
|
.token.number, |
||||
|
.token.constant, |
||||
|
.token.symbol, |
||||
|
.token.deleted { |
||||
|
color: #905; |
||||
|
} |
||||
|
|
||||
|
.token.selector, |
||||
|
.token.attr-name, |
||||
|
.token.string, |
||||
|
.token.char, |
||||
|
.token.builtin, |
||||
|
.token.inserted { |
||||
|
color: #690; |
||||
|
} |
||||
|
|
||||
|
.token.operator, |
||||
|
.token.entity, |
||||
|
.token.url, |
||||
|
.language-css .token.string, |
||||
|
.style .token.string { |
||||
|
color: #9a6e3a; |
||||
|
background: hsla(0, 0%, 100%, .5); |
||||
|
} |
||||
|
|
||||
|
.token.atrule, |
||||
|
.token.attr-value, |
||||
|
.token.keyword { |
||||
|
color: #07a; |
||||
|
} |
||||
|
|
||||
|
.token.function, |
||||
|
.token.class-name { |
||||
|
color: #DD4A68; |
||||
|
} |
||||
|
|
||||
|
.token.regex, |
||||
|
.token.important, |
||||
|
.token.variable { |
||||
|
color: #e90; |
||||
|
} |
||||
|
|
||||
|
.token.important, |
||||
|
.token.bold { |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.token.italic { |
||||
|
font-style: italic; |
||||
|
} |
||||
|
|
||||
|
.token.entity { |
||||
|
cursor: help; |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
|
||||
|
// Features specially written for demo
|
||||
|
|
||||
|
(function() { |
||||
|
|
||||
|
// language
|
||||
|
function language(params) { |
||||
|
|
||||
|
var lang = navigator.language||navigator.userLanguage;//常规浏览器语言和IE浏览器
|
||||
|
lang = lang.substr(0, 2);//截取lang前2位字符
|
||||
|
|
||||
|
return lang; |
||||
|
|
||||
|
} |
||||
|
// Tencent Forum Link Button
|
||||
|
function supportButton() { |
||||
|
const text = language() === 'zh' ? '反馈' : 'Forum'; |
||||
|
const link = language() === 'zh' ? 'https://support.qq.com/product/288322' : 'https://groups.google.com/g/luckysheet'; |
||||
|
|
||||
|
document.querySelector("body").insertAdjacentHTML('beforeend', '<a id="container" href="'+ link +'" target="_blank" style="z-index:2;width:50px;height:50px;line-height:50px;position:fixed;right:40px;bottom:86px;border-radius:50px;cursor:pointer;background:rgb(71,133,249);color:#fff;text-align:center;text-decoration:none;">'+ text +'</a>'); |
||||
|
} |
||||
|
|
||||
|
supportButton() |
||||
|
|
||||
|
/** |
||||
|
* Get url parameters |
||||
|
*/ |
||||
|
function getRequest() { |
||||
|
var vars = {}; |
||||
|
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, |
||||
|
function(m,key,value) { |
||||
|
vars[key] = value; |
||||
|
}); |
||||
|
return vars; |
||||
|
} |
||||
|
|
||||
|
window.luckysheetDemoUtil = { |
||||
|
language:language, |
||||
|
getRequest:getRequest |
||||
|
} |
||||
|
|
||||
|
})() |
@ -0,0 +1,4 @@ |
|||||
|
<template> |
||||
|
<div>dictionary</div> |
||||
|
</template> |
||||
|
<script setup lang="ts"></script> |
@ -0,0 +1,189 @@ |
|||||
|
<template> |
||||
|
<w-dialog |
||||
|
ref="dialogRef" |
||||
|
:title=" |
||||
|
$t('re.resources.designer.dialog.title', { |
||||
|
name: resourceRef?.name, |
||||
|
status: Formater.enum(Enums.DeployStatus)(resourceRef?.status), |
||||
|
version: resourceRef?.version, |
||||
|
}) |
||||
|
" |
||||
|
:can-maximize="false" |
||||
|
:maximized="true" |
||||
|
> |
||||
|
<q-splitter v-model="verticalSplitterRef" unit="px" separator-style="width: 3px"> |
||||
|
<template #before> |
||||
|
<Model |
||||
|
:resource="resourceRef" |
||||
|
@row-click=" |
||||
|
(evt, row, index) => { |
||||
|
modelRef = row; |
||||
|
if (row.parent) { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} else { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = true; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} |
||||
|
parameterGridRef?.refresh(); |
||||
|
} |
||||
|
" |
||||
|
@before-request-data=" |
||||
|
() => { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = false; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} |
||||
|
" |
||||
|
></Model> |
||||
|
</template> |
||||
|
|
||||
|
<template #after> |
||||
|
<div> |
||||
|
<q-splitter v-model="horizontalSplitterRef" unit="px" separator-style="height: 3px" horizontal> |
||||
|
<template #before> |
||||
|
<q-tabs v-model="statusReactive.parameterAndTestcaseTab" no-caps inline-label align="left"> |
||||
|
<q-tab v-if="statusReactive.isShowParameter" name="parameter" icon="bi-p-square" :label="$t('re.resources.designer.parameter.tab.title')" /> |
||||
|
<q-tab v-if="statusReactive.isShowTestCase" name="testcase" icon="bi-receipt" :label="$t('re.resources.designer.testcase.tab.title')" /> |
||||
|
</q-tabs> |
||||
|
<q-tab-panels v-model="statusReactive.parameterAndTestcaseTab" animated> |
||||
|
<q-tab-panel v-if="statusReactive.isShowParameter" name="parameter" class="px-0"> |
||||
|
<Parameter |
||||
|
:model="modelRef" |
||||
|
@row-click=" |
||||
|
(evt, row, index) => { |
||||
|
parameterRef = row; |
||||
|
if (row.type === 'IN') { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = true; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} else if (row.type === 'IN_OPTION') { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = true; |
||||
|
} else if (row.type == 'OUT' || row.type == 'INTERMEDIATE' || row.type == 'RULE_RESULT' || row.type == 'SINGLE_RULE_RESULT') { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = true; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} else { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} |
||||
|
// parameterGridRef?.refresh(); |
||||
|
} |
||||
|
" |
||||
|
@before-request-data=" |
||||
|
() => { |
||||
|
statusReactive.parameterAndTestcaseTab = 'parameter'; |
||||
|
statusReactive.isShowParameter = true; |
||||
|
statusReactive.isShowTestCase = false; |
||||
|
statusReactive.validatorAndProcessorAndOptionTab = 'validator'; |
||||
|
statusReactive.isShowValidator = false; |
||||
|
statusReactive.isShowProcessor = false; |
||||
|
statusReactive.isShowOption = false; |
||||
|
} |
||||
|
" |
||||
|
></Parameter> |
||||
|
</q-tab-panel> |
||||
|
<q-tab-panel v-if="statusReactive.isShowTestCase" name="testcase"> testCase</q-tab-panel> |
||||
|
</q-tab-panels> |
||||
|
</template> |
||||
|
<template #after> |
||||
|
<div v-if="statusReactive.isShowValidator"> |
||||
|
<Validator :parameter="parameterRef"></Validator> |
||||
|
</div> |
||||
|
<div v-if="statusReactive.isShowProcessor"> |
||||
|
<Processor :parameter="parameterRef"></Processor> |
||||
|
</div> |
||||
|
<div v-if="statusReactive.isShowOption"> |
||||
|
<Option :parameter="parameterRef"></Option> |
||||
|
</div> |
||||
|
</template> |
||||
|
</q-splitter> |
||||
|
</div> |
||||
|
</template> |
||||
|
</q-splitter> |
||||
|
</w-dialog> |
||||
|
</template> |
||||
|
<script setup lang="ts"> |
||||
|
import { ref, nextTick, reactive } from 'vue'; |
||||
|
import { Environment, Tools, EnumTools, Options, Formater } from 'platform-core'; |
||||
|
import Model from './Model.vue'; |
||||
|
import Parameter from './Parameter.vue'; |
||||
|
import Testcase from './Testcase.vue'; |
||||
|
import Validator from './Validator.vue'; |
||||
|
import Processor from './Processor.vue'; |
||||
|
import Option from './Option.vue'; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
opener: { type: Object, default: undefined }, |
||||
|
fetchDataUrl: { type: String, default: '' }, |
||||
|
dataUrl: { type: String, default: '' }, |
||||
|
foreignKey: { type: String, default: '' }, |
||||
|
foreignValue: { type: String, default: '' }, |
||||
|
}); |
||||
|
|
||||
|
const dialogRef = ref(); |
||||
|
const resourceRef = ref(); |
||||
|
const modelRef = ref({}); |
||||
|
const parameterRef = ref({}); |
||||
|
const horizontalSplitterRef = ref(500); |
||||
|
const verticalSplitterRef = ref(400); |
||||
|
const parameterGridRef = ref(); |
||||
|
const statusReactive = reactive({ |
||||
|
parameterAndTestcaseTab: 'parameter', |
||||
|
isShowParameter: false, |
||||
|
isShowTestCase: false, |
||||
|
validatorAndProcessorAndOptionTab: 'validator', |
||||
|
isShowValidator: false, |
||||
|
isShowProcessor: false, |
||||
|
isShowOption: false, |
||||
|
}); |
||||
|
|
||||
|
const open = (resource) => { |
||||
|
resourceRef.value = resource; |
||||
|
dialogRef.value.show(); |
||||
|
}; |
||||
|
|
||||
|
const close = () => { |
||||
|
dialogRef.value.hide(); |
||||
|
}; |
||||
|
|
||||
|
defineExpose({ |
||||
|
open, |
||||
|
close, |
||||
|
}); |
||||
|
|
||||
|
const Enums = await EnumTools.fetch(['io.sc.engine.rule.core.enums.DeployStatus']); |
||||
|
</script> |
@ -0,0 +1,26 @@ |
|||||
|
package io.sc.engine.rule.server.dictionary.exception; |
||||
|
|
||||
|
/** |
||||
|
* 数据字典已经存在违例类 |
||||
|
*/ |
||||
|
public class DictionaryAlreadyExistsException extends RuntimeException{ |
||||
|
public DictionaryAlreadyExistsException() { |
||||
|
super(); |
||||
|
} |
||||
|
|
||||
|
public DictionaryAlreadyExistsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { |
||||
|
super(message, cause, enableSuppression, writableStackTrace); |
||||
|
} |
||||
|
|
||||
|
public DictionaryAlreadyExistsException(String message, Throwable cause) { |
||||
|
super(message, cause); |
||||
|
} |
||||
|
|
||||
|
public DictionaryAlreadyExistsException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
public DictionaryAlreadyExistsException(Throwable cause) { |
||||
|
super(cause); |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
package io.sc.engine.rule.server.lib.entity.validator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.lib.entity.RangeIndicatorValidatorEntity; |
||||
|
import io.sc.engine.rule.server.lib.vo.validator.DateRangeIndicatorValidatorVo; |
||||
|
|
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DATE_RANGE") |
||||
|
@JsonTypeName("DATE_RANGE") |
||||
|
public class DateRangeIndicatorValidatorEntity extends RangeIndicatorValidatorEntity { |
||||
|
@Override |
||||
|
public DateRangeIndicatorValidatorVo toVo() { |
||||
|
DateRangeIndicatorValidatorVo vo =new DateRangeIndicatorValidatorVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setType(this.getType()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DATE_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
package io.sc.engine.rule.server.lib.entity.validator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.lib.entity.RangeIndicatorValidatorEntity; |
||||
|
import io.sc.engine.rule.server.lib.vo.validator.DecimalRangeIndicatorValidatorVo; |
||||
|
|
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DECIMAL_RANGE") |
||||
|
@JsonTypeName("DECIMAL_RANGE") |
||||
|
public class DecimalRangeIndicatorValidatorEntity extends RangeIndicatorValidatorEntity { |
||||
|
|
||||
|
@Override |
||||
|
public DecimalRangeIndicatorValidatorVo toVo() { |
||||
|
DecimalRangeIndicatorValidatorVo vo =new DecimalRangeIndicatorValidatorVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setType(this.getType()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DECIMAL_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package io.sc.engine.rule.server.lib.exception; |
||||
|
|
||||
|
/** |
||||
|
* CSV导入指标时,CSV 格式错误违例 |
||||
|
*/ |
||||
|
public class CsvIndicatorFormatException extends RuntimeException{ |
||||
|
public CsvIndicatorFormatException() { |
||||
|
super(); |
||||
|
} |
||||
|
|
||||
|
public CsvIndicatorFormatException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { |
||||
|
super(message, cause, enableSuppression, writableStackTrace); |
||||
|
} |
||||
|
|
||||
|
public CsvIndicatorFormatException(String message, Throwable cause) { |
||||
|
super(message, cause); |
||||
|
} |
||||
|
|
||||
|
public CsvIndicatorFormatException(String message) { |
||||
|
super(message); |
||||
|
} |
||||
|
|
||||
|
public CsvIndicatorFormatException(Throwable cause) { |
||||
|
super(cause); |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package io.sc.engine.rule.server.lib.vo.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.lib.vo.RangeIndicatorValidatorVo; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围)Vo 类 |
||||
|
*/ |
||||
|
public class DateRangeIndicatorValidatorVo extends RangeIndicatorValidatorVo { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DATE_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package io.sc.engine.rule.server.lib.vo.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.lib.vo.RangeIndicatorValidatorVo; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围)Vo 类 |
||||
|
*/ |
||||
|
public class DecimalRangeIndicatorValidatorVo extends RangeIndicatorValidatorVo { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DECIMAL_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,59 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.parameter; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ParameterType; |
||||
|
import io.sc.engine.rule.server.model.entity.ParameterEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.parameter.ConstantParameterVo; |
||||
|
|
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数(常量)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("CONSTANT") |
||||
|
@JsonTypeName("CONSTANT") |
||||
|
public class ConstantParameterEntity extends ParameterEntity { |
||||
|
|
||||
|
@Override |
||||
|
public ConstantParameterVo toVo() { |
||||
|
ConstantParameterVo vo =new ConstantParameterVo(); |
||||
|
super.toVo(vo); |
||||
|
this.setType(this.getType()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
public ConstantParameterEntity() {} |
||||
|
public ConstantParameterEntity(String id) { |
||||
|
this.id =id; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ParameterType getType() { |
||||
|
return ParameterType.CONSTANT; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "ConstantParameterEntity [" |
||||
|
+ " type=" + type |
||||
|
+ " id=" + id |
||||
|
+ ", code=" + code |
||||
|
+ ", name=" + name |
||||
|
+ ", description=" + description |
||||
|
+ ", order=" + order |
||||
|
|
||||
|
+ ", valueType" + valueType |
||||
|
+ ", valueScale" + valueScale |
||||
|
+ ", valueRoundingMode" + valueRoundingMode |
||||
|
+ ", valueTypeIsList" + valueTypeIsList |
||||
|
+ ", defaultValue=" + defaultValue |
||||
|
|
||||
|
+ ", creator=" + creator |
||||
|
+ ", createDate=" + createDate |
||||
|
+ ", lastModifier=" + lastModifier |
||||
|
+ ", lastModifyDate=" + lastModifyDate |
||||
|
+ "]"; |
||||
|
} |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.processor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.processor.DecisionTable2CParameterProcessorVo; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(简单决策表)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DECISION_TABLE_2C") |
||||
|
@JsonTypeName("DECISION_TABLE_2C") |
||||
|
public class DecisionTable2CParameterProcessorEntity extends ParameterProcessorEntity { |
||||
|
//简单决策表
|
||||
|
@Column(name="DECISION_TABLE_2C_") |
||||
|
private String decisionTable2C; |
||||
|
|
||||
|
@Override |
||||
|
public DecisionTable2CParameterProcessorVo toVo() { |
||||
|
DecisionTable2CParameterProcessorVo vo =new DecisionTable2CParameterProcessorVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setDecisionTable2C(this.getDecisionTable2C()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE_2C; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable2C() { |
||||
|
return decisionTable2C; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable2C(String decisionTable2C) { |
||||
|
this.decisionTable2C = decisionTable2C; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean replace(Map<String, String> mapping) { |
||||
|
String replaced =ExpressionReplacer.replace(this.decisionTable2C, mapping); |
||||
|
replaced =(replaced==null?"":replaced); |
||||
|
boolean result =false; |
||||
|
if(!replaced.equals(this.decisionTable2C)) { |
||||
|
result =true; |
||||
|
} |
||||
|
this.decisionTable2C =replaced; |
||||
|
return result; |
||||
|
} |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.processor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.processor.DecisionTableParameterProcessorVo; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策表)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DECISION_TABLE") |
||||
|
@JsonTypeName("DECISION_TABLE") |
||||
|
public class DecisionTableParameterProcessorEntity extends ParameterProcessorEntity { |
||||
|
//决策表
|
||||
|
@Column(name="DECISION_TABLE_") |
||||
|
private String decisionTable; |
||||
|
|
||||
|
@Override |
||||
|
public DecisionTableParameterProcessorVo toVo() { |
||||
|
DecisionTableParameterProcessorVo vo =new DecisionTableParameterProcessorVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setDecisionTable(this.getDecisionTable()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable() { |
||||
|
return decisionTable; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable(String decisionTable) { |
||||
|
this.decisionTable = decisionTable; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean replace(Map<String, String> mapping) { |
||||
|
String replaced =ExpressionReplacer.replace(this.decisionTable, mapping); |
||||
|
replaced =(replaced==null?"":replaced); |
||||
|
boolean result =false; |
||||
|
if(!replaced.equals(this.decisionTable)) { |
||||
|
result =true; |
||||
|
} |
||||
|
this.decisionTable =replaced; |
||||
|
return result; |
||||
|
} |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.processor; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.core.util.ExpressionReplacer; |
||||
|
import io.sc.engine.rule.server.model.entity.ParameterProcessorEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.processor.DecisionTreeParameterProcessorVo; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策树)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DECISION_TREE") |
||||
|
@JsonTypeName("DECISION_TREE") |
||||
|
public class DecisionTreeParameterProcessorEntity extends ParameterProcessorEntity { |
||||
|
//决策树
|
||||
|
@Column(name="DECISION_TREE_") |
||||
|
private String decisionTree; |
||||
|
|
||||
|
@Override |
||||
|
public DecisionTreeParameterProcessorVo toVo() { |
||||
|
DecisionTreeParameterProcessorVo vo =new DecisionTreeParameterProcessorVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setDecisionTree(this.getDecisionTree()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TREE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTree() { |
||||
|
return decisionTree; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTree(String decisionTree) { |
||||
|
this.decisionTree = decisionTree; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean replace(Map<String, String> mapping) { |
||||
|
String replaced =ExpressionReplacer.replace(this.decisionTree, mapping); |
||||
|
replaced =(replaced==null?"":replaced); |
||||
|
boolean result =false; |
||||
|
if(!replaced.equals(this.decisionTree)) { |
||||
|
result =true; |
||||
|
} |
||||
|
this.decisionTree =replaced; |
||||
|
return result; |
||||
|
} |
||||
|
} |
@ -0,0 +1,29 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.validator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.model.entity.RangeParameterValidatorEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.validator.DateRangeParameterValidatorVo; |
||||
|
|
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DATE_RANGE") |
||||
|
@JsonTypeName("DATE_RANGE") |
||||
|
public class DateRangeParameterValidatorEntity extends RangeParameterValidatorEntity { |
||||
|
@Override |
||||
|
public DateRangeParameterValidatorVo toVo() { |
||||
|
DateRangeParameterValidatorVo vo =new DateRangeParameterValidatorVo(); |
||||
|
super.toVo(vo); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DATE_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,29 @@ |
|||||
|
package io.sc.engine.rule.server.model.entity.validator; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.model.entity.RangeParameterValidatorEntity; |
||||
|
import io.sc.engine.rule.server.model.vo.validator.DecimalRangeParameterValidatorVo; |
||||
|
|
||||
|
import javax.persistence.DiscriminatorValue; |
||||
|
import javax.persistence.Entity; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围)实体类 |
||||
|
*/ |
||||
|
@Entity |
||||
|
@DiscriminatorValue("DECIMAL_RANGE") |
||||
|
@JsonTypeName("DECIMAL_RANGE") |
||||
|
public class DecimalRangeParameterValidatorEntity extends RangeParameterValidatorEntity { |
||||
|
@Override |
||||
|
public DecimalRangeParameterValidatorVo toVo() { |
||||
|
DecimalRangeParameterValidatorVo vo =new DecimalRangeParameterValidatorVo(); |
||||
|
super.toVo(vo); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DECIMAL_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.parameter; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ParameterType; |
||||
|
import io.sc.engine.rule.server.model.vo.ParameterVo; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数(常量) Vo 类 |
||||
|
*/ |
||||
|
public class ConstantParameterVo extends ParameterVo { |
||||
|
|
||||
|
@Override |
||||
|
public ParameterType getType() { |
||||
|
return ParameterType.CONSTANT; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.server.model.vo.ParameterProcessorVo; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(简单决策表)Vo 类 |
||||
|
*/ |
||||
|
public class DecisionTable2CParameterProcessorVo extends ParameterProcessorVo { |
||||
|
//简单决策表
|
||||
|
private String decisionTable2C; |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE_2C; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable2C() { |
||||
|
return decisionTable2C; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable2C(String decisionTable2C) { |
||||
|
this.decisionTable2C = decisionTable2C; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.server.model.vo.ParameterProcessorVo; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策表)Vo 类 |
||||
|
*/ |
||||
|
public class DecisionTableParameterProcessorVo extends ParameterProcessorVo { |
||||
|
//决策表
|
||||
|
private String decisionTable; |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TABLE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTable() { |
||||
|
return decisionTable; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTable(String decisionTable) { |
||||
|
this.decisionTable = decisionTable; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.processor; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ProcessorType; |
||||
|
import io.sc.engine.rule.server.model.vo.ParameterProcessorVo; |
||||
|
|
||||
|
/** |
||||
|
* 模型参数处理器(决策树)Vo 类 |
||||
|
*/ |
||||
|
public class DecisionTreeParameterProcessorVo extends ParameterProcessorVo { |
||||
|
//决策树
|
||||
|
private String decisionTree; |
||||
|
|
||||
|
@Override |
||||
|
public ProcessorType getType() { |
||||
|
return ProcessorType.DECISION_TREE; |
||||
|
} |
||||
|
|
||||
|
public String getDecisionTree() { |
||||
|
return decisionTree; |
||||
|
} |
||||
|
|
||||
|
public void setDecisionTree(String decisionTree) { |
||||
|
this.decisionTree = decisionTree; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.model.vo.RangeParameterValidatorVo; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(日期范围)实体类 |
||||
|
*/ |
||||
|
public class DateRangeParameterValidatorVo extends RangeParameterValidatorVo { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DATE_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package io.sc.engine.rule.server.model.vo.validator; |
||||
|
|
||||
|
import io.sc.engine.rule.core.enums.ValidatorType; |
||||
|
import io.sc.engine.rule.server.model.vo.RangeParameterValidatorVo; |
||||
|
|
||||
|
/** |
||||
|
* 验证器(小数范围)实体类 |
||||
|
*/ |
||||
|
public class DecimalRangeParameterValidatorVo extends RangeParameterValidatorVo { |
||||
|
@Override |
||||
|
public ValidatorType getType() { |
||||
|
return ValidatorType.DECIMAL_RANGE; |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
package io.sc.platform.attachment.api; |
||||
|
|
||||
|
import io.sc.platform.attachment.api.enums.PersistenceType; |
||||
|
import io.sc.platform.orm.api.vo.AuditorVo; |
||||
|
|
||||
|
public class DatabaseAttachmentVo extends AttachmentVo { |
||||
|
private byte[] bytes; |
||||
|
|
||||
|
public byte[] getBytes() { |
||||
|
return bytes; |
||||
|
} |
||||
|
|
||||
|
public void setBytes(byte[] bytes) { |
||||
|
this.bytes = bytes; |
||||
|
} |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
package io.sc.platform.attachment.jpa.entity; |
||||
|
|
||||
|
import com.fasterxml.jackson.annotation.JsonTypeName; |
||||
|
import io.sc.platform.attachment.api.DatabaseAttachmentVo; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
|
||||
|
@Entity |
||||
|
@DiscriminatorValue("DATABASE") |
||||
|
@JsonTypeName("DATABASE") |
||||
|
public class DatabaseAttachmentEntity extends AttachmentEntity { |
||||
|
//附件字节数组
|
||||
|
@Lob |
||||
|
@Basic(fetch = FetchType.LAZY) |
||||
|
@Column(name = "ATTACHMENT_", columnDefinition = "BLOB",nullable=true) |
||||
|
private byte[] bytes; |
||||
|
|
||||
|
@Override |
||||
|
public DatabaseAttachmentVo toVo() { |
||||
|
DatabaseAttachmentVo vo =new DatabaseAttachmentVo(); |
||||
|
super.toVo(vo); |
||||
|
vo.setBytes(this.getBytes()); |
||||
|
return vo; |
||||
|
} |
||||
|
|
||||
|
public byte[] getBytes() { |
||||
|
return bytes; |
||||
|
} |
||||
|
|
||||
|
public void setBytes(byte[] bytes) { |
||||
|
this.bytes = bytes; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue