package foundation.dao; import java.io.IOException; import java.math.BigDecimal; import java.net.URLDecoder; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; import foundation.dao.version.VersionRequest; import foundation.data.meta.field.FieldsRuntime; import foundation.data.meta.property.MetaType; import foundation.data.object.DataJoin; import foundation.data.object.DataJoins; import foundation.data.object.DataObject; import foundation.data.object.IParamProvider; import foundation.handler.DataPool; import foundation.handler.DataPoolType; import foundation.json.JArrayReader; import foundation.json.JObjectReader; import foundation.json.JSONReader; import foundation.json.JType; import foundation.route.Operation; import foundation.server.config.DBaseType; import foundation.token.IOnlineUser; import foundation.translator.ITranslator; import foundation.translator.Translator; import foundation.util.MapList; import foundation.util.Util; import foundation.variant.provider.DataEvent; import foundation.variant.provider.IVariantsProvider; import foundation.variant.provider.VariantProviderType; public class DataReader extends JObjectReader implements IVariantsProvider, IParamProvider { private static Set excludeNames; private static Set stopChars; private Operation operation; private DataPool dataPool; private Domain domain; private MapList params; static { excludeNames = new HashSet(); excludeNames.add("dataname"); excludeNames.add("filter"); excludeNames.add("orderby"); excludeNames.add("page"); stopChars = new HashSet(); stopChars.add(' '); stopChars.add('\r'); stopChars.add('\n'); } public DataReader(Operation operation, DataPool dataPool) throws Exception { super(); //1. this.operation = operation; this.dataPool = dataPool; DataPoolType type = dataPool.getType(); if (DataPoolType.Get == type) { loadGetRequestData(dataPool); } else if (DataPoolType.Post == type) { loadPostRequestData(dataPool); } else if (DataPoolType.MultiPart == type) { loadMultiPartParams(); } } private void loadGetRequestData(DataPool dataPool) throws Exception { params = dataPool.getParams(); domain = new Domain(this, operation); domain.setEmpty(true); loadDomain(domain); } private void loadPostRequestData(DataPool dataPool) throws Exception { //1. read JSON body JObjectReader jObjectReader = dataPool.getJObjectReader(); this.items = jObjectReader.getItems(); //2. read parameters params = dataPool.getParams(); //3. read domain domain = new Domain(this, operation); loadDomain(domain); } private void loadMultiPartParams() { params = dataPool.getParams(); } public synchronized Domain getDomain() throws Exception { return domain; } public void loadDomain(Domain domain) throws Exception { //1. empty boolean empty = isEmpty(); domain.setEmpty(empty); //2. token String token = getString(IDataLetter.Token); domain.setToken(token); //3. data name and partial name String dataName = getString(IDataLetter.DataName); if (!Util.isEmpty(dataName)) { int pos = dataName.indexOf("."); if (pos > 0) { String partialName = dataName.substring(pos + 1); dataName = dataName.substring(0, pos); domain.setPartialName(partialName); } domain.setDataName(dataName); } //4. parent id and id String parentId = getString(IDataLetter.ParentID); domain.setParentId(parentId); String id = getString(IDataLetter.ID); domain.setId(id); //5. String operator = getString(IDataLetter.Operator); if (Util.isEmpty(operator)) { operator = operation.getOperator(); } domain.setOperator(operator); OperatorCode operatorCode = OperatorCode.parse(operator); domain.setOperatorCode(operatorCode); //6. meta code boolean attachMeta = getBoolean(IDataLetter.AttachMeta, false); MetaType metaType = attachMeta ? MetaType.Unknow : MetaType.None; if (MetaType.Unknow == metaType && OperatorCode.GetBatch.equals(operatorCode)) { metaType = MetaType.List; } domain.setMetaType(metaType); String scene = getString(IDataLetter.Scene); domain.setScene(scene); //7. host String hostId = getString(IDataLetter.HostID); domain.setHostId(hostId); if (has(IDataLetter.HostItems)) { Set hostItems = new HashSet(); JArrayReader array = getReader(IDataLetter.HostItems, JType.Array); for (JSONReader value: array) { String itemName = value.getString(null); if (itemName == null) { continue; } itemName = itemName.toLowerCase(); hostItems.add(itemName); } domain.setHostItems(hostItems); } } public VersionRequest loadVersionRequest() { if (!has(IDataLetter.Version)) { return null; } VersionRequest versionRequest = domain.getVersionRequest(); if (versionRequest == null) { versionRequest = new VersionRequest(); domain.setVersionRequest(versionRequest); } JObjectReader versionReader = getReader(IDataLetter.Version, JType.Object); String get = versionReader.getString("get"); String compare = versionReader.getString("compare"); versionRequest.set(get, compare); return versionRequest; } public void loadFilterFromJSON(DataObject dataObject, Filter filter) throws Exception { FieldsRuntime meta = dataObject.getTableFieldMetas(); DBaseType dbaseType = dataObject.getDbaseType(); String tableName = dataObject.getTableOrViewName(); DataJoins dataJoins = dataObject.getDataJoins(); //1. 如果直接指定ID,读取ID String id = domain.getId(); if (!Util.isEmpty(id)) { filter.add(getFullFieldName(tableName, "id"), id); } //2. 如果指定了MasterID, 读取MasterID String masterId = domain.getParentId(); if (!Util.isEmpty(masterId)) { filter.add(getFullFieldName(tableName, "parent_id"), masterId); } //3. 从过滤条件中读取 if (!has(IDataLetter.Filter)) { return; } JType dataType = getType(IDataLetter.Filter); //3.1 read string if (JType.String == dataType) { String value = getString(IDataLetter.Filter); value = decodeString(value); doReadOneFilerLineFromJSON(dbaseType, tableName, dataJoins, value, filter); } //3.2 read array else if (JType.Array == dataType) { JArrayReader array = getReader(IDataLetter.Filter, JType.Array); for (JSONReader line: array) { doReadOneFilerLineFromJSON(dbaseType, tableName, dataJoins, meta, line, filter); } } //3.3 read object else if (JType.Object == dataType) { JSONReader line = getReader(IDataLetter.Filter, JType.Object); doReadOneFilerLineFromJSON(dbaseType, tableName, dataJoins, meta, line, filter); } } private void doReadOneFilerLineFromJSON(DBaseType dbaseType, String tableName, DataJoins dataJoins, String value, Filter filter) { int pos = value.indexOf(DataJoin.TableJoinConnector); if (pos >= 0) { value = value.replace(DataJoin.TableJoinConnector, "."); } filter.add(value); } private void doReadOneFilerLineFromJSON(DBaseType dbaseType, String tableName, DataJoins dataJoins, FieldsRuntime meta, JSONReader line, Filter filter) throws Exception { String fieldName = line.getString(IDataLetter.Filter_Field); String value = line.getString(IDataLetter.Filter_Value); String operator = line.getString(IDataLetter.Filter_Operator); if (Util.isEmpty(fieldName) || Util.isEmpty(value)) { return; } int pos = 0; //1. 如果表中包含该字段,直接加入 if (meta.contains(fieldName)) { ITranslator translator = meta.getValueTranslator(fieldName); JType valueType = line.getType(IDataLetter.Filter_Value); //1.1 如果是 2023-08-20 >= date <= 2023-08-25 这种类型 if (JType.Array == valueType) { List list = line.getStringList(IDataLetter.Filter_Value); if (list.size() != 2) { return; } String left = getFullFieldName(tableName, fieldName) + ">=" + translator.toSqlString(dbaseType, list.get(0)); String right = getFullFieldName(tableName, fieldName) + "<=" + translator.toSqlString(dbaseType, list.get(1)); filter.add("(" + left + " and " + right + ")"); return; } //1.2 如果是 code = 00001 这种类型 value = URLDecoder.decode(value, "UTF-8"); value = translator.toSqlString(dbaseType, value); filter.add(getFullFieldName(tableName, fieldName), operator, value); return; } //2. 检查 Join 表 else if ((pos = fieldName.indexOf(DataJoin.TableJoinConnector)) > 0) { tableName = fieldName.substring(0, pos); fieldName = fieldName.substring(pos + 2); meta = dataJoins.getJoinFieldsMeta(tableName); if (meta == null) { return; } ITranslator translator = meta.getValueTranslator(fieldName); if (translator == null) { return; } value = URLDecoder.decode(value, "UTF-8"); value = translator.toSqlString(dbaseType, value); filter.add(getFullFieldName(tableName, fieldName), operator, value); } //3. 自定义SQL中的字段,有可能存在.的情况 else if (fieldName.indexOf(".") > 0) { tableName = fieldName.substring(pos); value = URLDecoder.decode(value, "UTF-8"); filter.add(fieldName, operator, Translator.toSqlString(dbaseType, value)); } } public static String getFullFieldName(String tableName, String fieldName) { if (Util.isEmpty(tableName)) { return fieldName; } return tableName + "." + fieldName; } public void loadPageOrderByFromJSON(DataObject dataObject, Page page, OrderBy orderBy) throws Exception { //1. read page if (has(IDataLetter.Page)) { JObjectReader pageReader = getReader("page", JType.Object); //1.1 如果请求分页参数为空,不需要加上分页 if (pageReader != null) { Integer pageSize = pageReader.getInteger(IDataLetter.Page_Size, null); page.setPageSize(pageSize); Integer pageNo = pageReader.getInteger(IDataLetter.Page_No, null); page.setPageNo(pageNo); } } else { //2. 如果不传分页参数,不需要加上分页 page.setEmpty(true); } //2. read order by if (has(IDataLetter.OrderBy)) { String value = getString(IDataLetter.OrderBy); if (!Util.isEmpty(value)) { orderBy.add(value); } else { OrderBy defaultOrderBy = dataObject.getDefaultOrderBy(); orderBy.addAll(defaultOrderBy); } } //3 add page order by if ((!page.isEmpty()) && (orderBy.isEmpty())) { FieldsRuntime meta = dataObject.getBatchBrowseFieldMetas(); if (meta.contains(OrderBy.PageOrderByField)) { String tableName = dataObject.getTableOrViewName(); if (!Util.isEmpty(tableName)) { orderBy.add(tableName + "." + OrderBy.PageOrderByField); } } } } public void loadOrderByFromJSON(DataObject dataObject, OrderBy orderBy) throws Exception { if (has(IDataLetter.OrderBy)) { String value = getString(IDataLetter.OrderBy); if (!Util.isEmpty(value)) { orderBy.add(value); } else { OrderBy defaultOrderBy = dataObject.getDefaultOrderBy(); orderBy.addAll(defaultOrderBy); } } } public Domain loadFilterPageOrderByFromJSON(DataObject dataObject, Filter filter, Page page, OrderBy orderBy) throws Exception { //1. load filter loadFilterFromJSON(dataObject, filter); //2. load page and order by loadPageOrderByFromJSON(dataObject, page, orderBy); //3. return return domain; } private String decodeString(String value) { try { value = URLDecoder.decode(value, "UTF-8"); return value; } catch (Exception e) { return value; } } public DataPackage getDataPackage() throws Exception { return domain.getDataPackage(); } public VersionRequest getVersionRequest() { return domain.getVersionRequest(); } public Operation getOperation() { return operation; } public String getOperator() { if (operation == null) { return null; } return operation.getOperator(); } public void loadOneParameter(String name, String value) { params.add(name, value); } @Override public boolean has(String name) { boolean result = super.has(name); if (result) { return result; } if (params == null) { return result; } result = params.contains(name); return result; } @Override public JType getType(String name) { JType result = super.getType(name); if (JType.Empty != result) { return result; } result = params.contains(name) ? JType.String : JType.Empty; return result; } @Override public String getString(String name) { String result = super.getString(name); if ((result == null) && (params != null)) { result = params.get(name); } return result; } public BigDecimal getBigDecimal(String name, BigDecimal defaultValue) { String result = super.getString(name); if ((Util.isEmpty(result)) && (params != null)) { return defaultValue; } return new BigDecimal(result); } public String getRequestBody() throws IOException { if (dataPool == null) { return null; } return dataPool.getBody(); } @Override public String getProviderName() { return this.getClass().getSimpleName(); } @Override public VariantProviderType getProviderType() { return VariantProviderType.Transiant; } @Override public boolean containsVariant(String name) { if (name == null) { return false; } if (excludeNames.contains(name.toLowerCase())) { return false; } return has(name); } @Override public Object getVariantValue(DataEvent dataEvent, String name) { return getString(name); } @Override public Set getVariantNames() { Set result = new HashSet(); Set keys = items.getKeySet(); for (String name: keys) { if (excludeNames.contains(name.toLowerCase())) { continue; } result.add(name); } return result; } public DataPool getDataPool() { return dataPool; } public void setDataPool(DataPool dataPool) { this.dataPool = dataPool; } public String getBody() throws IOException { return dataPool.getBody(); } public HttpServletRequest getRequest() { return dataPool.getRequest(); } public IOnlineUser getUser() { return dataPool.getUser(); } }