| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | public class CoolGenerator { |
| | | |
| | |
| | | private String primaryKeyType; |
| | | private String majorColumn; |
| | | private String systemPackage; |
| | | private Map<String, String> existingFieldLabels = new LinkedHashMap<>(); |
| | | |
| | | public void build() throws Exception { |
| | | init(); |
| | |
| | | primaryKeyColumn = resolvePrimaryKeyColumn(); |
| | | primaryKeyType = resolvePrimaryKeyType(); |
| | | majorColumn = resolveMajorColumn(); |
| | | existingFieldLabels = loadExistingFieldLabels(); |
| | | entityImport = buildEntityImports(); |
| | | entityContent = buildEntityContent(); |
| | | xmlContent = buildXmlContent(); |
| | |
| | | private static List<Column> getColumns(Connection connection, String table, boolean withForeignKey, SqlOsType sqlOsType) throws Exception { |
| | | List<Column> columns = new ArrayList<>(); |
| | | DatabaseMetaData metaData = connection.getMetaData(); |
| | | TableRef tableRef = parseTableRef(table); |
| | | TableRef tableRef = resolveTableRef(connection, table, sqlOsType); |
| | | Set<String> primaryKeys = new LinkedHashSet<>(); |
| | | ResultSet pkRs = metaData.getPrimaryKeys(tableRef.catalog, tableRef.schema, tableRef.table); |
| | | try { |
| | |
| | | pkRs.close(); |
| | | } |
| | | |
| | | Map<String, Column> uniqueColumns = new LinkedHashMap<>(); |
| | | ResultSet columnRs = metaData.getColumns(tableRef.catalog, tableRef.schema, tableRef.table, null); |
| | | try { |
| | | while (columnRs.next()) { |
| | | String columnName = columnRs.getString("COLUMN_NAME"); |
| | | if (uniqueColumns.containsKey(columnName)) { |
| | | continue; |
| | | } |
| | | int sqlType = columnRs.getInt("DATA_TYPE"); |
| | | String type = GeneratorUtils.getType(sqlType); |
| | | if (Cools.isEmpty(type)) { |
| | |
| | | boolean mainKey = primaryKey && isAutoIncrement(columnRs); |
| | | boolean notNull = columnRs.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls; |
| | | Integer length = GeneratorUtils.getColumnLength(columnRs.getString("TYPE_NAME")); |
| | | columns.add(new Column(connection, columnName, type, remarks, primaryKey, mainKey, notNull, length, |
| | | uniqueColumns.put(columnName, new Column(connection, columnName, type, remarks, primaryKey, mainKey, notNull, length, |
| | | withForeignKey, sqlOsType)); |
| | | } |
| | | } finally { |
| | | columnRs.close(); |
| | | } |
| | | columns.addAll(uniqueColumns.values()); |
| | | for (Column column : columns) { |
| | | System.out.println(column.toString()); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | private static TableRef parseTableRef(String table) { |
| | | private static TableRef resolveTableRef(Connection connection, String table, SqlOsType sqlOsType) throws SQLException { |
| | | String catalog = connection.getCatalog(); |
| | | String schema = null; |
| | | try { |
| | | schema = connection.getSchema(); |
| | | } catch (SQLException ignored) { |
| | | } |
| | | if (table != null && table.contains(".")) { |
| | | String[] arr = table.split("\\."); |
| | | return new TableRef(null, arr[0], arr[arr.length - 1]); |
| | | String scope = arr[0]; |
| | | String tableName = arr[arr.length - 1]; |
| | | if (sqlOsType == SqlOsType.MYSQL) { |
| | | return new TableRef(scope, null, tableName); |
| | | } |
| | | return new TableRef(catalog, scope, tableName); |
| | | } |
| | | return new TableRef(null, null, table); |
| | | if (sqlOsType == SqlOsType.MYSQL) { |
| | | return new TableRef(catalog, null, table); |
| | | } |
| | | return new TableRef(catalog, schema, table); |
| | | } |
| | | |
| | | private String resolvePrimaryKeyColumn() { |
| | |
| | | builder.append(" {\n"); |
| | | builder.append(" field: '").append(column.getHumpName()).append("',\n"); |
| | | builder.append(" columnName: '").append(column.getName()).append("',\n"); |
| | | builder.append(" label: '").append(escapeJs(GeneratorUtils.supportHtmlName(column.getComment()))).append("',\n"); |
| | | builder.append(" label: '").append(escapeJs(resolveVueFieldLabel(column))).append("',\n"); |
| | | builder.append(" tableProp: '").append(resolveDisplayField(column)).append("',\n"); |
| | | builder.append(" exportField: '").append(resolveDisplayField(column)).append("',\n"); |
| | | builder.append(" kind: '").append(resolveVueFieldKind(column)).append("',\n"); |
| | |
| | | return column.getHumpName(); |
| | | } |
| | | |
| | | private String resolveVueFieldLabel(Column column) { |
| | | String label = GeneratorUtils.supportHtmlName(column.getComment()); |
| | | if (!Cools.isEmpty(label)) { |
| | | return label; |
| | | } |
| | | label = existingFieldLabels.get(column.getHumpName()); |
| | | if (!Cools.isEmpty(label)) { |
| | | return label; |
| | | } |
| | | return buildFallbackLabel(column); |
| | | } |
| | | |
| | | private String buildFallbackLabel(Column column) { |
| | | String raw = Cools.isEmpty(column.getName()) ? column.getHumpName() : column.getName(); |
| | | if (Cools.isEmpty(raw)) { |
| | | return ""; |
| | | } |
| | | raw = raw.replace("$", "") |
| | | .replaceAll("([a-z0-9])([A-Z])", "$1 $2") |
| | | .replace("_", " ") |
| | | .replaceAll("\\s+", " ") |
| | | .trim(); |
| | | if (Cools.isEmpty(raw)) { |
| | | return ""; |
| | | } |
| | | StringBuilder builder = new StringBuilder(); |
| | | for (String item : raw.split(" ")) { |
| | | if (item.isEmpty()) { |
| | | continue; |
| | | } |
| | | if (builder.length() > 0) { |
| | | builder.append(" "); |
| | | } |
| | | builder.append(item.substring(0, 1).toUpperCase()).append(item.substring(1)); |
| | | } |
| | | return builder.toString(); |
| | | } |
| | | |
| | | private Map<String, String> loadExistingFieldLabels() { |
| | | Map<String, String> labelMap = new LinkedHashMap<>(); |
| | | Path jsPath = Paths.get(frontendPrefixPath + "src/main/webapp/static/js/" + simpleEntityName + "/" + simpleEntityName + ".js"); |
| | | Path htmlPath = Paths.get(frontendPrefixPath + "src/main/webapp/views/" + simpleEntityName + "/" + simpleEntityName + ".html"); |
| | | Path detailPath = Paths.get(frontendPrefixPath + "src/main/webapp/views/" + simpleEntityName + "/" + simpleEntityName + "_detail.html"); |
| | | try { |
| | | mergeExistingLabels(labelMap, jsPath, Pattern.compile("field:\\s*'([^']+)'.*?label:\\s*'([^']+)'", Pattern.DOTALL)); |
| | | mergeExistingLabels(labelMap, jsPath, Pattern.compile("field:\\s*'([^']+)'[^\\n]*title:\\s*'([^']+)'")); |
| | | mergeExistingLabels(labelMap, detailPath, Pattern.compile("<label[^>]*>(.*?)</label>.*?<(?:(?:input)|(?:select))[^>]*\\sid=\"([^\"]+)\"", Pattern.DOTALL), true); |
| | | mergeExistingLabels(labelMap, htmlPath, Pattern.compile("name=\"([^\"]+)\"[^>]*placeholder=\"([^\"]+)\"")); |
| | | } catch (IOException ignored) { |
| | | } |
| | | return labelMap; |
| | | } |
| | | |
| | | private void mergeExistingLabels(Map<String, String> labelMap, Path path, Pattern pattern) throws IOException { |
| | | mergeExistingLabels(labelMap, path, pattern, false); |
| | | } |
| | | |
| | | private void mergeExistingLabels(Map<String, String> labelMap, Path path, Pattern pattern, boolean reversed) throws IOException { |
| | | if (path == null || !Files.exists(path)) { |
| | | return; |
| | | } |
| | | String content = Files.readString(path, StandardCharsets.UTF_8); |
| | | Matcher matcher = pattern.matcher(content); |
| | | while (matcher.find()) { |
| | | String field = normalizeExistingField(reversed ? matcher.group(2) : matcher.group(1)); |
| | | String label = cleanExistingLabel(reversed ? matcher.group(1) : matcher.group(2)); |
| | | if (Cools.isEmpty(field, label) || labelMap.containsKey(field)) { |
| | | continue; |
| | | } |
| | | labelMap.put(field, label); |
| | | } |
| | | } |
| | | |
| | | private String normalizeExistingField(String field) { |
| | | if (Cools.isEmpty(field)) { |
| | | return ""; |
| | | } |
| | | field = field.trim(); |
| | | if (field.endsWith("$")) { |
| | | field = field.substring(0, field.length() - 1); |
| | | } |
| | | if (field.contains("_")) { |
| | | return GeneratorUtils._convert(field, true); |
| | | } |
| | | return field; |
| | | } |
| | | |
| | | private String cleanExistingLabel(String label) { |
| | | if (Cools.isEmpty(label)) { |
| | | return ""; |
| | | } |
| | | label = label.replaceAll("<[^>]+>", "") |
| | | .replace(":", "") |
| | | .replace(":", "") |
| | | .trim(); |
| | | return label; |
| | | } |
| | | |
| | | private List<Column> getNonPrimaryColumns() { |
| | | List<Column> result = new ArrayList<>(); |
| | | for (Column column : columns) { |