[analysis]添加AbstractResolvableDataSet类,重构相关数据集实现类

This commit is contained in:
datagear 2020-09-01 11:37:04 +08:00
parent 695ec6c2ab
commit 9bd3f101c4
13 changed files with 120 additions and 493 deletions

View File

@ -72,6 +72,9 @@ public interface DataSet extends Identifiable
/**
* 获取{@linkplain DataSetResult}
* <p>
* 返回结果中的数据项应已转换为与{@linkplain #getProperties()}{@linkplain DataSetProperty#getType()}类型一致
* </p>
*
* @param paramValues
* {@linkplain #getParams()}所描述的参数值映射表其关键字是{@linkplain DataSetParam#getName()}

View File

@ -11,14 +11,8 @@ package org.datagear.analysis;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.datagear.util.StringUtil;
/**
* 数据集属性信息
* <p>
@ -66,54 +60,6 @@ public class DataSetProperty extends AbstractDataNameType implements Serializabl
return getClass().getSimpleName() + " [name=" + getName() + ", type=" + getType() + ", label=" + label + "]";
}
/**
* 连接给定列表的{@linkplain #getLabel()}
* <p>
* 如果{@code dataSetProperties}{@code null}将返回空字符串
* </p>
*
* @param dataSetProperties
* @param splitter
*/
public static String concatLabels(List<DataSetProperty> dataSetProperties, String splitter)
{
if (dataSetProperties == null)
return "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < dataSetProperties.size(); i++)
{
DataSetProperty dataSetProperty = dataSetProperties.get(i);
String label = dataSetProperty.getLabel();
if (!StringUtil.isEmpty(label))
{
if (sb.length() > 0)
sb.append(splitter);
sb.append(label);
}
}
return sb.toString();
}
/**
* 拆分由{@linkplain #concatLabels(List, String)}连接的字符串
*
* @param labelText
* @param splitter
* @return
*/
public static String[] splitLabels(String labelText, String splitter)
{
if (labelText == null)
return new String[0];
return StringUtil.split(labelText, splitter, true);
}
/**
* {@linkplain DataSetProperty#getType()}类型枚举
*
@ -149,270 +95,6 @@ public class DataSetProperty extends AbstractDataNameType implements Serializabl
/** 未知类型 */
public static final String UNKNOWN = "UNKNOWN";
/**
* 是否是{@linkplain #STRING}
*
* @param dataType
* @return
*/
public static boolean isString(String dataType)
{
return STRING.equals(dataType);
}
/**
* 是否是{@linkplain #BOOLEAN}
*
* @param dataType
* @return
*/
public static boolean isBoolean(String dataType)
{
return BOOLEAN.equals(dataType);
}
/**
* 是否是{@linkplain #NUMBER}
*
* @param dataType
* @return
*/
public static boolean isNumber(String dataType)
{
return NUMBER.equals(dataType);
}
/**
* 是否是{@linkplain #INTEGER}
*
* @param dataType
* @return
*/
public static boolean isInteger(String dataType)
{
return INTEGER.equals(dataType);
}
/**
* 是否是{@linkplain #DECIMAL}
*
* @param dataType
* @return
*/
public static boolean isDecimal(String dataType)
{
return DECIMAL.equals(dataType);
}
/**
* 是否是数值型的
*
* @param dataType
* @return
*/
public static boolean isNumberic(String dataType)
{
return (isNumber(dataType) || isInteger(dataType) || isDecimal(dataType));
}
/**
* 是否是{@linkplain #DATE}
*
* @param dataType
* @return
*/
public static boolean isDate(String dataType)
{
return DATE.equals(dataType);
}
/**
* 是否是{@linkplain #TIME}
*
* @param dataType
* @return
*/
public static boolean isTime(String dataType)
{
return TIME.equals(dataType);
}
/**
* 是否是{@linkplain #TIMESTAMP}
*
* @param dataType
* @return
*/
public static boolean isTimestamp(String dataType)
{
return TIMESTAMP.equals(dataType);
}
/**
* 是否是{@linkplain #UNKNOWN}
*
* @param dataType
* @return
*/
public static boolean isUnknown(String dataType)
{
return UNKNOWN.equals(dataType);
}
/**
* {@linkplain #STRING}类型的值转换为{@linkplain String}
* <p>
* {@code value}参数必须是{@linkplain String}类型
* </p>
*
* @param value
* @return
*/
public static String castString(Object value)
{
return (String) value;
}
/**
* {@linkplain #BOOLEAN}类型的值转换为{@linkplain Boolean}
* <p>
* {@code value}参数必须是{@linkplain Boolean}类型
* </p>
*
* @param value
* @return
*/
public static Boolean castBoolean(Object value)
{
return (Boolean) value;
}
/**
* {@linkplain #INTEGER}类型的值转换为{@linkplain Number}
* <p>
* {@code value}参数必须是{@linkplain Number}或其子类型
* </p>
*
* @param value
* @return
*/
public static Number castInteger(Object value)
{
return (Number) value;
}
/**
* {@linkplain #INTEGER}类型的值转换为{@linkplain BigInteger}
* <p>
* {@code value}参数必须是{@linkplain Number}或其子类型
* </p>
*
* @param value
* @return
*/
public static BigInteger castBigInteger(Object value)
{
Number number = castInteger(value);
if (number == null)
return null;
else if (number instanceof BigInteger)
return (BigInteger) number;
else
return BigInteger.valueOf(number.longValue());
}
/**
* {@linkplain #DECIMAL}类型的值转换为{@linkplain Number}
* <p>
* {@code value}参数必须是{@linkplain Number}或其子类型
* </p>
*
* @param value
* @return
*/
public static Number castDecimal(Object value)
{
return (Number) value;
}
/**
* {@linkplain #DECIMAL}类型的值转换为{@linkplain BigDecimal}
* <p>
* {@code value}参数必须是{@linkplain Number}或其子类型
* </p>
*
* @param value
* @return
*/
public static BigDecimal castBigDecimal(Object value)
{
Number number = castInteger(value);
if (number == null)
return null;
else if (number instanceof BigDecimal)
return (BigDecimal) number;
else
return BigDecimal.valueOf(number.doubleValue());
}
/**
* {@linkplain #DATE}类型的值转换为{@linkplain Date}
* <p>
* {@code value}参数必须是{@linkplain Date}或其子类型
* </p>
*
* @param value
* @return
*/
public static Date castDate(Object value)
{
return (Date) value;
}
/**
* {@linkplain #TIME}类型的值转换为{@linkplain Time}
* <p>
* {@code value}参数必须是{@linkplain Date}或其子类型
* </p>
*
* @param value
* @return
*/
public static Time castTime(Object value)
{
Date date = castDate(value);
if (date == null)
return null;
else if (date instanceof Time)
return (Time) value;
else
return new Time(date.getTime());
}
/**
* {@linkplain #TIME}类型的值转换为{@linkplain Timestamp}
* <p>
* {@code value}参数必须是{@linkplain Date}或其子类型
* </p>
*
* @param value
* @return
*/
public static Timestamp castTimestamp(Object value)
{
Date date = castDate(value);
if (date == null)
return null;
else if (date instanceof Timestamp)
return (Timestamp) value;
else
return new Timestamp(date.getTime());
}
/**
* 解析对象的数据类型
*

View File

@ -30,7 +30,7 @@ import org.datagear.util.IOUtil;
* @author datagear@163.com
*
*/
public abstract class AbstractCsvDataSet extends AbstractFmkTemplateDataSet implements ResolvableDataSet
public abstract class AbstractCsvDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
{
/** 作为名称行的行号 */
private int nameRow = -1;
@ -82,38 +82,14 @@ public abstract class AbstractCsvDataSet extends AbstractFmkTemplateDataSet impl
this.nameRow = nameRow;
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
List<DataSetProperty> properties = getProperties();
if (properties == null || properties.isEmpty())
throw new DataSetException("[getProperties()] must not be empty");
ResolvedDataSetResult result = resolveResult(paramValues, properties);
return result.getResult();
}
@Override
public ResolvedDataSetResult resolve(Map<String, ?> paramValues) throws DataSetException
{
return resolveResult(paramValues, null);
}
/**
* 解析结果
* <p>
* 如果{@linkplain #getCsvReader(Map)}返回的{@linkplain TemplateResolvedSource#hasResolvedTemplate()}
* 此方法将返回{@linkplain TemplateResolvedDataSetResult}
* </p>
*
* @param paramValues
* @param properties
* 允许为{@code null}此时会自动解析
* @return
* @throws DataSetException
*/
@Override
protected ResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
@ -157,15 +133,6 @@ public abstract class AbstractCsvDataSet extends AbstractFmkTemplateDataSet impl
*/
protected abstract TemplateResolvedSource<Reader> getCsvReader(Map<String, ?> paramValues) throws Throwable;
/**
* 解析结果
*
* @param csvReader
* @param properties
* 允许为{@code null}此时会自动解析
* @return
* @throws Throwable
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected ResolvedDataSetResult resolveResult(Reader csvReader, List<DataSetProperty> properties) throws Throwable
{

View File

@ -27,6 +27,9 @@ import org.datagear.analysis.DataSetProperty;
*/
public abstract class AbstractDataSet extends AbstractIdentifiable implements DataSet
{
/** 默认Freemarker模板解析器 */
public static final DataSetFmkTemplateResolver FMK_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver();
private String name;
private List<DataSetProperty> properties;
@ -196,12 +199,12 @@ public abstract class AbstractDataSet extends AbstractIdentifiable implements Da
}
/**
* 解析属性类型
* 解析{@linkplain DataSetProperty.DataType}类型
*
* @param value
* @return
*/
protected String resolveDataType(Object value)
protected String resolvePropertyDataType(Object value)
{
return DataSetProperty.DataType.resolveDataType(value);
}
@ -254,4 +257,19 @@ public abstract class AbstractDataSet extends AbstractIdentifiable implements Da
return maps;
}
/**
* 将指定文本作为Freemarker模板解析
*
* @param text
* @param paramValues
* @return
*/
protected String resolveAsFmkTemplate(String text, Map<String, ?> paramValues)
{
if (text == null)
return null;
return FMK_TEMPLATE_RESOLVER.resolve(text, paramValues);
}
}

View File

@ -55,7 +55,7 @@ import org.slf4j.LoggerFactory;
* @author datagear@163.com
*
*/
public abstract class AbstractExcelDataSet extends AbstractFmkTemplateDataSet implements ResolvableDataSet
public abstract class AbstractExcelDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
{
protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractExcelDataSet.class);
@ -224,33 +224,7 @@ public abstract class AbstractExcelDataSet extends AbstractFmkTemplateDataSet im
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
List<DataSetProperty> properties = getProperties();
if (properties == null || properties.isEmpty())
throw new DataSetException("[getProperties()] must not be empty");
ResolvedDataSetResult result = resolve(paramValues, properties);
return result.getResult();
}
@Override
public ResolvedDataSetResult resolve(Map<String, ?> paramValues) throws DataSetException
{
return resolve(paramValues, null);
}
/**
* 解析Excel结果
*
* @param paramValues
* @param properties
* 允许为{@code null}此时会自动解析
* @return
* @throws DataSetException
*/
protected ResolvedDataSetResult resolve(Map<String, ?> paramValues, List<DataSetProperty> properties)
protected ResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
File file = getExcelFile(paramValues);
@ -481,7 +455,7 @@ public abstract class AbstractExcelDataSet extends AbstractFmkTemplateDataSet im
if (dataRowIdx == 0)
{
// 空单元格先不处理数据类型等待后续有非空单元格再判断
String dataType = (cellValue == null ? "" : resolveDataType(cellValue));
String dataType = (cellValue == null ? "" : resolvePropertyDataType(cellValue));
// 名称行不一定在数据行之前所以此时可能无法确定属性名
property = new DataSetProperty("should-be-set-later", dataType);
@ -492,7 +466,7 @@ public abstract class AbstractExcelDataSet extends AbstractFmkTemplateDataSet im
property = properties.get(dataColIdx);
if (StringUtil.isEmpty(property.getType()) && cellValue != null)
property.setType(resolveDataType(cellValue));
property.setType(resolvePropertyDataType(cellValue));
}
return property;

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.analysis.support;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetProperty;
/**
* 抽象Freemarker模板{@linkplain DataSet}
*
* @author datagear@163.com
*
*/
public abstract class AbstractFmkTemplateDataSet extends AbstractDataSet
{
public static final DataSetFmkTemplateResolver TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver();
public AbstractFmkTemplateDataSet()
{
super();
}
public AbstractFmkTemplateDataSet(String id, String name, List<DataSetProperty> properties)
{
super(id, name, properties);
}
protected String resolveTemplate(String template, Map<String, ?> paramValues)
{
if (template == null)
return null;
return TEMPLATE_RESOLVER.resolve(template, paramValues);
}
}

View File

@ -33,7 +33,7 @@ import com.fasterxml.jackson.databind.node.ValueNode;
* @author datagear@163.com
*
*/
public abstract class AbstractJsonDataSet extends AbstractFmkTemplateDataSet implements ResolvableDataSet
public abstract class AbstractJsonDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
{
public AbstractJsonDataSet()
{
@ -51,38 +51,14 @@ public abstract class AbstractJsonDataSet extends AbstractFmkTemplateDataSet imp
super(id, name, properties);
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
List<DataSetProperty> properties = getProperties();
if (properties == null || properties.isEmpty())
throw new DataSetException("[getProperties()] must not be empty");
ResolvedDataSetResult result = resolveResult(paramValues, properties);
return result.getResult();
}
@Override
public ResolvedDataSetResult resolve(Map<String, ?> paramValues) throws DataSetException
{
return resolveResult(paramValues, null);
}
/**
* 解析结果
* <p>
* 如果{@linkplain #getJsonReader(Map)}返回的{@linkplain TemplateResolvedSource#hasResolvedTemplate()}
* 此方法将返回{@linkplain TemplateResolvedDataSetResult}
* </p>
*
* @param paramValues
* @param properties
* 允许为{@code null}此时会自动解析
* @return
* @throws DataSetException
*/
@Override
protected ResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
@ -318,8 +294,8 @@ public abstract class AbstractJsonDataSet extends AbstractFmkTemplateDataSet imp
DataSetProperty property = new DataSetProperty(entry.getKey(), type);
// JSON数值只有NUMBER类型
if (DataSetProperty.DataType.isInteger(property.getType())
|| DataSetProperty.DataType.isDecimal(property.getType()))
if (DataSetProperty.DataType.INTEGER.equals(property.getType())
|| DataSetProperty.DataType.DECIMAL.equals(property.getType()))
property.setType(DataSetProperty.DataType.NUMBER);
properties.add(property);

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2018 datagear.tech. All Rights Reserved.
*/
/**
*
*/
package org.datagear.analysis.support;
import java.util.List;
import java.util.Map;
import org.datagear.analysis.DataSetException;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetResult;
import org.datagear.analysis.ResolvableDataSet;
import org.datagear.analysis.ResolvedDataSetResult;
/**
* 抽象{@linkplain ResolvableDataSet}
*
* @author datagear@163.com
*
*/
public abstract class AbstractResolvableDataSet extends AbstractDataSet implements ResolvableDataSet
{
public AbstractResolvableDataSet()
{
super();
}
public AbstractResolvableDataSet(String id, String name, List<DataSetProperty> properties)
{
super(id, name, properties);
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
List<DataSetProperty> properties = getProperties();
if (properties == null || properties.isEmpty())
throw new DataSetException("[getProperties()] must not be empty");
ResolvedDataSetResult result = resolveResult(paramValues, properties);
return result.getResult();
}
@Override
public ResolvedDataSetResult resolve(Map<String, ?> paramValues) throws DataSetException
{
return resolveResult(paramValues, getProperties());
}
/**
* 解析结果
*
* @param paramValues
* @param properties
* 允许为空此时应自动解析并设置返回结果的{@linkplain ResolvedDataSetResult#setProperties(List)}
* 如果不为空直接将{@code properties}作为解析数据依据 使用它处理结果数据
* 并设置为返回结果的{@linkplain ResolvedDataSetResult#setProperties(List)}
* @return
* @throws DataSetException
*/
protected abstract ResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException;
}

View File

@ -73,7 +73,7 @@ public class CsvValueDataSet extends AbstractCsvDataSet
@Override
protected TemplateResolvedSource<Reader> getCsvReader(Map<String, ?> paramValues) throws Throwable
{
String csv = resolveTemplate(this.value, paramValues);
return new TemplateResolvedSource<Reader>(IOUtil.getReader(csv), csv);
String csv = resolveAsFmkTemplate(this.value, paramValues);
return new TemplateResolvedSource<>(IOUtil.getReader(csv), csv);
}
}

View File

@ -64,7 +64,7 @@ public class JsonValueDataSet extends AbstractJsonDataSet
@Override
protected TemplateResolvedSource<Reader> getJsonReader(Map<String, ?> paramValues) throws Throwable
{
String json = resolveTemplate(this.value, paramValues);
return new TemplateResolvedSource<Reader>(IOUtil.getReader(json), json);
String json = resolveAsFmkTemplate(this.value, paramValues);
return new TemplateResolvedSource<>(IOUtil.getReader(json), json);
}
}

View File

@ -42,7 +42,7 @@ import org.datagear.util.resource.ConnectionFactory;
* @author datagear@163.com
*
*/
public class SqlDataSet extends AbstractFmkTemplateDataSet implements ResolvableDataSet
public class SqlDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
{
protected static final JdbcSupport JDBC_SUPPORT = new JdbcSupport();
@ -91,37 +91,17 @@ public class SqlDataSet extends AbstractFmkTemplateDataSet implements Resolvable
this.sql = sql;
}
@Override
public DataSetResult getResult(Map<String, ?> paramValues) throws DataSetException
{
List<DataSetProperty> properties = getProperties();
if (properties == null || properties.isEmpty())
throw new DataSetException("[getProperties()] must not be empty");
ResolvedDataSetResult result = resolveResult(paramValues, properties);
return result.getResult();
}
@Override
public TemplateResolvedDataSetResult resolve(Map<String, ?> paramValues) throws DataSetException
{
return resolveResult(paramValues, null);
}
/**
* 解析结果
*
* @param paramValues
* @param properties
* 允许为{@code null}此时会自动解析
* @return
* @throws DataSetException
*/
@Override
protected TemplateResolvedDataSetResult resolveResult(Map<String, ?> paramValues, List<DataSetProperty> properties)
throws DataSetException
{
String sql = resolveTemplate(getSql(), paramValues);
String sql = resolveAsFmkTemplate(getSql(), paramValues);
Connection cn = null;
@ -232,12 +212,12 @@ public class SqlDataSet extends AbstractFmkTemplateDataSet implements Resolvable
if (resolveProperties && rowIdx == 0)
{
@JDBCCompatiblity("某些驱动程序可能存在一种情况,列类型是toPropertyDataType()无法识别的,但是实际值是允许的,"
@JDBCCompatiblity("某些驱动程序可能存在一种情况,列类型会被toPropertyDataType()解析为DataType.UNKNOWN,但是实际值是允许的,"
+ "比如PostgreSQL-42.2.5驱动对于[SELECT 'aaa' as NAME]语句结果的SQL类型是Types.OTHER但实际值是允许的字符串")
boolean resolveTypeByValue = (DataType.UNKNOWN.equals(property.getType()));
if (resolveTypeByValue)
property.setType(resolveDataType(value));
property.setType(resolvePropertyDataType(value));
}
value = convertToPropertyDataType(converter, value, property);
@ -265,7 +245,7 @@ public class SqlDataSet extends AbstractFmkTemplateDataSet implements Resolvable
* @throws SQLException
* @throws SqlDataSetUnsupportedSqlTypeException
*/
public String toPropertyDataType(SqlType sqlType, String columnName)
protected String toPropertyDataType(SqlType sqlType, String columnName)
throws SQLException, SqlDataSetUnsupportedSqlTypeException
{
String dataType = null;

View File

@ -16,7 +16,6 @@ import java.util.Map;
import org.datagear.analysis.DataSetParam;
import org.datagear.analysis.DataSetProperty;
import org.datagear.analysis.DataSetProperty.DataType;
import org.datagear.analysis.DataSetResult;
import org.datagear.util.JdbcUtil;
import org.datagear.util.resource.SimpleConnectionFactory;
@ -61,10 +60,12 @@ public class SqlDataSetTest extends DBTestSupport
String sql = "SELECT ID, NAME FROM T_ACCOUNT <#if id??>WHERE ID = ${id} AND NAME != '${name}'</#if>";
List<DataSetProperty> dataSetProperties = Arrays.asList(new DataSetProperty("ID", DataType.INTEGER),
new DataSetProperty("NAME", DataType.STRING));
List<DataSetParam> dataSetParams = Arrays.asList(new DataSetParam("id", DataType.STRING, true),
new DataSetParam("name", DataType.STRING, true));
List<DataSetProperty> dataSetProperties = Arrays.asList(
new DataSetProperty("ID", DataSetProperty.DataType.INTEGER),
new DataSetProperty("NAME", DataSetProperty.DataType.STRING));
List<DataSetParam> dataSetParams = Arrays.asList(new DataSetParam("id", DataSetParam.DataType.STRING, true),
new DataSetParam("name", DataSetParam.DataType.STRING, true));
SqlDataSet sqlDataSet = new SqlDataSet("1", "1", dataSetProperties, connectionFactory, sql);
sqlDataSet.setParams(dataSetParams);

View File

@ -21,7 +21,7 @@ import javax.servlet.http.HttpServletResponse;
import org.datagear.analysis.DataSet;
import org.datagear.analysis.DataSetParam;
import org.datagear.analysis.ResolvedDataSetResult;
import org.datagear.analysis.support.AbstractFmkTemplateDataSet;
import org.datagear.analysis.support.AbstractDataSet;
import org.datagear.analysis.support.CsvValueDataSet;
import org.datagear.analysis.support.DataSetFmkTemplateResolver;
import org.datagear.analysis.support.DataSetParamValueConverter;
@ -760,7 +760,7 @@ public class DataSetController extends AbstractSchemaConnController
protected DataSetFmkTemplateResolver getDataSetFmkTemplateResolver()
{
return AbstractFmkTemplateDataSet.TEMPLATE_RESOLVER;
return AbstractDataSet.FMK_TEMPLATE_RESOLVER;
}
protected void checkSaveEntity(DataSetEntity dataSet)