001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.apidoc; 017 018import com.alibaba.fastjson.JSONObject; 019import com.alibaba.fastjson.parser.Feature; 020import com.jfinal.kit.PathKit; 021import com.jfinal.kit.StrKit; 022import com.jfinal.plugin.activerecord.generator.ColumnMeta; 023import com.jfinal.plugin.activerecord.generator.MetaBuilder; 024import com.jfinal.plugin.activerecord.generator.TableMeta; 025import com.zaxxer.hikari.HikariConfig; 026import com.zaxxer.hikari.HikariDataSource; 027import io.jboot.Jboot; 028import io.jboot.codegen.CodeGenHelpler; 029import io.jboot.db.datasource.DataSourceConfig; 030import io.jboot.db.driver.DriverClassNames; 031import io.jboot.utils.DateUtil; 032import io.jboot.utils.FileUtil; 033import io.jboot.utils.StrUtil; 034 035import javax.sql.DataSource; 036import java.io.File; 037import java.math.BigDecimal; 038import java.math.BigInteger; 039import java.time.temporal.Temporal; 040import java.util.Date; 041import java.util.LinkedHashMap; 042import java.util.List; 043import java.util.Map; 044import java.util.function.Predicate; 045import java.util.stream.Collectors; 046 047public class ApiJsonGenerator { 048 049 /** 050 * 生成 Mock Json 数据 051 */ 052 public static void genMockJson() { 053 genMockJson(new JsonGeneratorConfig("api-mock.json")); 054 } 055 056 057 /** 058 * 生成 Mock Json 数据 059 * 060 * @param config 061 */ 062 public static void genMockJson(JsonGeneratorConfig config) { 063 064 Map<String, Map<String, Object>> root = new LinkedHashMap<>(); 065 066 File file = new File(config.getJsonFilePathPathAbsolute()); 067 //如果文件存在,则先读取其配置,然后再修改 068 if (file.exists()) { 069 String oldJson = FileUtil.readString(file); 070 JSONObject rootJsonObject = JSONObject.parseObject(oldJson, Feature.OrderedField); 071 if (rootJsonObject != null && !rootJsonObject.isEmpty()) { 072 for (String classOrSimpleName : rootJsonObject.keySet()) { 073 root.put(classOrSimpleName, rootJsonObject.getJSONObject(classOrSimpleName)); 074 } 075 } 076 } 077 078 MetaBuilder builder = CodeGenHelpler.createMetaBuilder(config.getDatasource(), config.getType(), false); 079 List<TableMeta> tableMetas = builder.build(); 080 081 if (config.tableMetaFilter != null) { 082 tableMetas = tableMetas.stream() 083 .filter(config.tableMetaFilter) 084 .collect(Collectors.toList()); 085 } 086 087 088 for (TableMeta tableMeta : tableMetas) { 089 Map<String, Object> classMockData = new LinkedHashMap<>(); 090 for (ColumnMeta columnMeta : tableMeta.columnMetas) { 091 Object mockData = createMockData(columnMeta); 092 if (mockData != null && !"".equals(mockData)) { 093 classMockData.put(columnMeta.attrName, mockData); 094 } 095 } 096 if (!classMockData.isEmpty()) { 097 root.put(StrKit.firstCharToLowerCase(tableMeta.modelName), classMockData); 098 } 099 } 100 101 102 String jsonContent = JSONObject.toJSONString(root, true); 103 FileUtil.writeString(file, jsonContent); 104 105 System.out.println("Gen Remarks Json File ----->" + FileUtil.getCanonicalPath(file)); 106 } 107 108 109 private static Object createMockData(ColumnMeta columnMeta) { 110 if (String.class.getName().equals(columnMeta.javaType)) { 111 return columnMeta.remarks; 112 } else if (Date.class.getName().equals(columnMeta.javaType)) { 113 return DateUtil.toDateTimeString(new Date()); 114 } else if (isTemporal(columnMeta.javaType)) { 115 return DateUtil.toDateTimeString(new Date()); 116 } else if (int.class.getName().equals(columnMeta.javaType)) { 117 return 1; 118 } else if (Integer.class.getName().equals(columnMeta.javaType)) { 119 return 100; 120 } else if (long.class.getName().equals(columnMeta.javaType)) { 121 return 1; 122 } else if (Long.class.getName().equals(columnMeta.javaType)) { 123 return 100; 124 } else if (short.class.getName().equals(columnMeta.javaType)) { 125 return 1; 126 } else if (Short.class.getName().equals(columnMeta.javaType)) { 127 return 100; 128 } else if (BigDecimal.class.getName().equals(columnMeta.javaType)) { 129 return BigDecimal.ONE; 130 } else if (BigInteger.class.getName().equals(columnMeta.javaType)) { 131 return BigDecimal.ONE; 132 } else if (boolean.class.getName().equals(columnMeta.javaType)) { 133 return Boolean.TRUE; 134 } else if (Boolean.class.getName().equals(columnMeta.javaType)) { 135 return Boolean.TRUE; 136 } else if (float.class.getName().equals(columnMeta.javaType)) { 137 return 1.0f; 138 } else if (Float.class.getName().equals(columnMeta.javaType)) { 139 return 1.0f; 140 } else if (double.class.getName().equals(columnMeta.javaType)) { 141 return 1.0d; 142 } else if (Double.class.getName().equals(columnMeta.javaType)) { 143 return 1.0d; 144 } else { 145 return ""; 146 } 147 } 148 149 private static boolean isTemporal(String javaType) { 150 try { 151 return Temporal.class.isAssignableFrom(Class.forName(javaType)); 152 } catch (ClassNotFoundException e) { 153 e.printStackTrace(); 154 } 155 return false; 156 } 157 158 159 /** 160 * 生成 Model 的字段备注数据 161 */ 162 public static void genRemarksJson() { 163 genRemarksJson(new JsonGeneratorConfig("api-remarks.json")); 164 } 165 166 /** 167 * 生成 Model 的字段备注数据 168 */ 169 public static void genRemarksJson(JsonGeneratorConfig config) { 170 171 Map<String, Map<String, String>> root = new LinkedHashMap<>(); 172 173 File file = new File(config.getJsonFilePathPathAbsolute()); 174 //如果文件存在,则先读取其配置,然后再修改 175 if (file.exists()) { 176 String oldJson = FileUtil.readString(file); 177 JSONObject rootJsonObject = JSONObject.parseObject(oldJson, Feature.OrderedField); 178 if (rootJsonObject != null && !rootJsonObject.isEmpty()) { 179 for (String classOrSimpleName : rootJsonObject.keySet()) { 180 Map<String, String> remarks = new LinkedHashMap<>(); 181 JSONObject modelRemarks = rootJsonObject.getJSONObject(classOrSimpleName); 182 modelRemarks.forEach((k, v) -> remarks.put(k, String.valueOf(v))); 183 root.put(classOrSimpleName, remarks); 184 } 185 } 186 } 187 188 189 MetaBuilder builder = CodeGenHelpler.createMetaBuilder(config.getDatasource(), config.getType(), false); 190 List<TableMeta> tableMetas = builder.build(); 191 192 if (config.tableMetaFilter != null) { 193 tableMetas = tableMetas.stream() 194 .filter(config.tableMetaFilter) 195 .collect(Collectors.toList()); 196 } 197 198 199 for (TableMeta tableMeta : tableMetas) { 200 Map<String, String> modelRemarks = new LinkedHashMap<>(); 201 for (ColumnMeta columnMeta : tableMeta.columnMetas) { 202 if (StrUtil.isNotBlank(columnMeta.remarks)) { 203 modelRemarks.put(columnMeta.attrName, columnMeta.remarks); 204 } 205 } 206 if (!modelRemarks.isEmpty()) { 207 root.put(StrKit.firstCharToLowerCase(tableMeta.modelName), modelRemarks); 208 } 209 } 210 211 212 String jsonContent = JSONObject.toJSONString(root, true); 213 FileUtil.writeString(file, jsonContent); 214 215 System.out.println("Gen Remarks Json File ----->" + FileUtil.getCanonicalPath(file)); 216 } 217 218 219 public static class JsonGeneratorConfig { 220 221 private boolean useJbootDatasource = true; 222 223 private String jdbcUrl; 224 private String userName; 225 private String password; 226 private String type = DataSourceConfig.TYPE_MYSQL; 227 228 private String jsonFilePath; 229 private Predicate<TableMeta> tableMetaFilter; 230 231 public JsonGeneratorConfig() { 232 } 233 234 public JsonGeneratorConfig(String jsonFilePath) { 235 this.jsonFilePath = jsonFilePath; 236 } 237 238 public boolean isUseJbootDatasource() { 239 return useJbootDatasource; 240 } 241 242 public void setUseJbootDatasource(boolean useJbootDatasource) { 243 this.useJbootDatasource = useJbootDatasource; 244 } 245 246 public String getJdbcUrl() { 247 return jdbcUrl; 248 } 249 250 public void setJdbcUrl(String jdbcUrl) { 251 this.jdbcUrl = jdbcUrl; 252 } 253 254 public String getUserName() { 255 return userName; 256 } 257 258 public void setUserName(String userName) { 259 this.userName = userName; 260 } 261 262 public String getPassword() { 263 return password; 264 } 265 266 public void setPassword(String password) { 267 this.password = password; 268 } 269 270 public String getType() { 271 return type; 272 } 273 274 public void setType(String type) { 275 this.type = type; 276 } 277 278 public String getJsonFilePath() { 279 return jsonFilePath; 280 } 281 282 public void setJsonFilePath(String jsonFilePath) { 283 this.jsonFilePath = jsonFilePath; 284 } 285 286 public String getJsonFilePathPathAbsolute() { 287 if (FileUtil.isAbsolutePath(jsonFilePath)) { 288 return jsonFilePath; 289 } 290 return FileUtil.getCanonicalPath(new File(PathKit.getRootClassPath(), "../../" + jsonFilePath)); 291 } 292 293 294 public Predicate<TableMeta> getTableMetaFilter() { 295 return tableMetaFilter; 296 } 297 298 public void setTableMetaFilter(Predicate<TableMeta> tableMetaFilter) { 299 this.tableMetaFilter = tableMetaFilter; 300 } 301 302 303 public DataSource getDatasource() { 304 if (useJbootDatasource) { 305 DataSourceConfig datasourceConfig = Jboot.config(DataSourceConfig.class, "jboot.datasource"); 306 HikariConfig config = new HikariConfig(); 307 config.setJdbcUrl(datasourceConfig.getUrl()); 308 config.setUsername(datasourceConfig.getUser()); 309 config.setPassword(datasourceConfig.getPassword()); 310 config.setDriverClassName(datasourceConfig.getDriverClassName()); 311 312 return new HikariDataSource(config); 313 } else { 314 HikariConfig config = new HikariConfig(); 315 config.setJdbcUrl(this.jdbcUrl); 316 config.setUsername(this.userName); 317 config.setPassword(this.password); 318 config.setDriverClassName(DriverClassNames.getDefaultDriverClass(this.type)); 319 320 return new HikariDataSource(config); 321 } 322 } 323 } 324}