package org.hsweb.web.service.impl.form; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.commons.beanutils.BeanUtils; import org.hsweb.commons.StringUtils; import org.hsweb.expands.script.engine.DynamicScriptEngine; import org.hsweb.expands.script.engine.DynamicScriptEngineFactory; import org.hsweb.ezorm.rdb.meta.RDBColumnMetaData; import org.hsweb.ezorm.rdb.meta.RDBTableMetaData; import org.hsweb.ezorm.rdb.meta.converter.ClobValueConverter; import org.hsweb.ezorm.rdb.meta.converter.DateTimeConverter; import org.hsweb.ezorm.rdb.meta.converter.JSONValueConverter; import org.hsweb.ezorm.rdb.render.dialect.Dialect; import org.hsweb.ezorm.rdb.simple.trigger.ScriptTraggerSupport; import org.hsweb.web.bean.po.form.Form; import org.hsweb.web.core.datasource.DataSourceHolder; import org.hsweb.web.service.form.FormParser; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; import java.sql.JDBCType; import java.util.*; @Service public class DefaultFormParser implements FormParser { @Autowired(required = false) private List<FormParser.Listener> listeners; public void initField(RDBColumnMetaData column) { Dialect dialect = DataSourceHolder.getActiveDatabaseType().getDialect(); if (column.getDataType() == null) { if (column.getJdbcType() == null) { throw new UnsupportedOperationException("请指定jdbcType或者dataType"); } dialect.buildDataType(column); } if (column.getJdbcType() == null) { String dataType = column.getDataType(); if (dataType != null) { if (dataType.contains("varchar")) { column.setJdbcType(JDBCType.VARCHAR); String className = column.getJavaType().getSimpleName(); if (!typeMapper.containsKey(className)) { column.setValueConverter(new JSONValueConverter(column.getJavaType(), column.getValueConverter())); } } else if (dataType.contains("date") || dataType.contains("timestamp") || dataType.contains("datetime")) { column.setJdbcType(JDBCType.DATE); String format = column.getProperty("date-format", "yyyy-MM-dd HH:mm:ss").toString(); column.setValueConverter(new DateTimeConverter(format, column.getJavaType())); } else if (dataType.contains("clob")) { column.setJdbcType(JDBCType.CLOB); column.setValueConverter(new ClobValueConverter()); String className = column.getJavaType().getSimpleName(); if (!typeMapper.containsKey(className)) { column.setValueConverter(new JSONValueConverter(column.getJavaType(), column.getValueConverter())); } } else if (dataType.contains("number") || dataType.contains("int") || dataType.contains("double") || dataType.contains("tinyint")) { column.setJdbcType(JDBCType.NUMERIC); } else { column.setJdbcType(JDBCType.VARCHAR); String className = column.getJavaType().getSimpleName(); if (!typeMapper.containsKey(className)) { column.setValueConverter(new JSONValueConverter(column.getJavaType(), column.getValueConverter())); } } } } } @Override public RDBTableMetaData parse(Form form) { DynamicScriptEngine scriptEngine = DynamicScriptEngineFactory.getEngine("groovy"); String meta = form.getMeta(); RDBTableMetaData metaData = new RDBTableMetaData(); metaData.setProperty("version", form.getRelease()); metaData.setName(form.getName()); metaData.setComment(form.getRemark()); JSONObject object = JSON.parseObject(meta); int[] sortIndex = new int[1]; Map<String, RDBColumnMetaData> tmp = new HashMap<>(); object.forEach((id, field) -> { RDBColumnMetaData columnMetaData = new RDBColumnMetaData(); columnMetaData.setProperty("field-id", id); tmp.put(id, columnMetaData); columnMetaData.setSortIndex(sortIndex[0]++); JSONArray obj = ((JSONArray) field); obj.forEach((defT) -> { JSONObject def = ((JSONObject) defT); String key = def.getString("key"); Object value = def.get("value"); if ("main".equals(id)) { if ("alias".equals(key)) { if (!StringUtils.isNullOrEmpty(value)) metaData.setAlias(String.valueOf(value)); } else if ("trigger".equals(key)) { List<JSONObject> jsonArray = JSON.parseArray((String) value, JSONObject.class); jsonArray.forEach(jsonObject -> { String name = jsonObject.getString("key"); String script = jsonObject.getString("value"); String scriptId = String.valueOf(script.hashCode()); if (!scriptEngine.compiled(scriptId)) { try { scriptEngine.compile(scriptId, script); } catch (Exception e) { throw new RuntimeException("编译脚本异常", e); } } ScriptTraggerSupport scriptTrigger = new ScriptTraggerSupport(scriptEngine, scriptId); metaData.on(name, scriptTrigger); }); return; } else metaData.setProperty(key, value); return; } if ("validator-list".equals(key)) { Set<String> validatorList = new LinkedHashSet<>(); if (value instanceof String) { List<JSONObject> jsonArray = JSON.parseArray((String) value, JSONObject.class); jsonArray.forEach(json -> { String validator = json.getString("validator"); if (validatorSupport(validator)) validatorList.add(validator); }); } columnMetaData.setValidator(validatorList); return; } Field ftmp = ReflectionUtils.findField(RDBColumnMetaData.class, key); if (ftmp != null) { try { if ("javaType".equals(key)) value = mapperJavaType(value.toString()); BeanUtils.setProperty(columnMetaData, key, value); } catch (RuntimeException e) { throw e; } catch (Exception e) { } } else { if (value instanceof String) { try { String stringValue = ((String) value).trim(); if (stringValue.startsWith("[") || stringValue.startsWith("{")) value = JSON.parse(stringValue); } catch (Throwable e) { } } columnMetaData.setProperty(key, value); } }); //name为空的时候 不保存此字段 if (!"main".equals(id) && !StringUtils.isNullOrEmpty(columnMetaData.getName())) { initField(columnMetaData); if (StringUtils.isNullOrEmpty(columnMetaData.getAlias())) columnMetaData.setAlias(columnMetaData.getName()); metaData.addColumn(columnMetaData); } }); if (listeners != null) { listeners.forEach(listener -> listener.afterParse(metaData)); } Document document = Jsoup.parse(form.getHtml()); Elements elements = document.select("[field-id]"); for (int i = 0; i < elements.size(); i++) { RDBColumnMetaData column = tmp.get(elements.get(i).attr("field-id")); if (column != null) column.setSortIndex(i); } return metaData; } protected boolean validatorSupport(String validator) { return !StringUtils.isNullOrEmpty(validator); } protected static Map<String, Class> typeMapper = new HashMap() {{ put("", String.class); put("null", String.class); put("string", String.class); put("String", String.class); put("str", String.class); put("int", Integer.class); put("double", Double.class); put("boolean", Boolean.class); put("byte", Byte.class); put("char", Character.class); put("float", Double.class); put("long", Long.class); put("short", Short.class); put("date", Date.class); put("Date", Date.class); }}; public Class mapperJavaType(String str) { Class clazz = typeMapper.get(str); if (clazz == null) try { clazz = Class.forName(str); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } return clazz; } @Override public String parseHtml(Form form) { RDBTableMetaData metaData = parse(form); Element html = Jsoup.parse(form.getHtml()); metaData.getColumns().forEach((field) -> { String field_id = field.getProperty("field-id", "").toString(); if (!"".equals(field_id)) { Elements elements = html.select("[field-id=\"" + field_id + "\"]"); Element input = elements.first(); if (null != input) { List<Map> domProperty = field.getProperty("domProperty", "[]").toList(); domProperty.forEach((property) -> { Object value = property.get("value"); Object key = property.get("key"); if (StringUtils.isNullOrEmpty(value) || StringUtils.isNullOrEmpty(key)) return; input.attr(String.valueOf(property.get("key")), String.valueOf(value)); }); input.attr("name", field.getAlias()); input.attr("id", field.getAlias()); input.attr("class", field.getProperty("class").toString()); } } }); return html.toString(); } }