public List generate() {
//v3对应着3.0.11 OpenAPI的代码数据
if (optsV3 != null) {
return new DefaultGenerator().opts(optsV3).generate();
} else if (optsV2 != null) {
//v2对应着swagger的代码数据
return new io.swagger.codegen.DefaultGenerator().opts(optsV2).generate();
}
throw new RuntimeException("missing opts input");
}
三.总指挥官
这里分析的是3.0.11的DefaultGenerator
DefaultGenerator.generate:
生成各种文件的流程是:处理数据,找到模板,生成文件
public List generate() {
if (swagger == null || config == null) {
throw new RuntimeException("missing swagger input or config!");
}
//添加一些生成器属性(名字,版本,生成时间等)和测试数据
configureGeneratorProperties();
//添加appname,license等信息
configureSwaggerInfo();
//处理model里面内联(包括array)
InlineModelResolver inlineModelResolver = new InlineModelResolver();
inlineModelResolver.flatten(swagger);
List files = new ArrayList();
// 1.生成models
List
1.生成models
private void generateModels(List files, List allModels) {
if (!generateModels) {
return;
}
//获取所有的model数据
final Map schemas = this.openAPI.getComponents().getSchemas();
if (schemas == null) {
return;
}
......
for (String name : modelKeys) {
try {
//不需要生成可以导入的类
if(config.importMapping().containsKey(name)) {
LOGGER.info("Model " + name + " not imported due to import mapping");
continue;
}
Schema schema = schemas.get(name);
Map schemaMap = new HashMap<>();
schemaMap.put(name, schema);
//处理model数据(包括了包路径,属性信息)
Map models = processModels(config, schemaMap, schemas);
//存放类名
//toModelName多处使用,为了统一名字格式(非字母下划线数字字符会被去掉)
models.put("classname", config.toModelName(name));
models.putAll(config.additionalProperties());
allProcessedModels.put(name, models);
final List modelList = (List) models.get("models");
if (modelList == null || modelList.isEmpty()) {
continue;
}
//处理内部类?
for (Object object : modelList) {
Map modelMap = (Map) object;
CodegenModel codegenModel = null;
if (modelMap.containsKey("oneOf-model")) {
codegenModel = (CodegenModel) modelMap.get("oneOf-model");
}
if (modelMap.containsKey("anyOf-model")) {
codegenModel = (CodegenModel) modelMap.get("anyOf-model");
}
if (codegenModel != null) {
models = processModel(codegenModel, config, schemas);
models.put("classname", config.toModelName(codegenModel.name));
models.putAll(config.additionalProperties());
allProcessedModels.put(codegenModel.name, models);
break;
}
}
} catch (Exception e) {
throw new RuntimeException("Could not process model '" + name + "'" + ".Please make sure that your schema is correct!", e);
}
}
// 预处理model
allProcessedModels = config.postProcessAllModels(allProcessedModels);
for (String modelName: allProcessedModels.keySet()) {
//获取model信息
Map models = (Map)allProcessedModels.get(modelName);
try {
//不需要生成importMapping中有的类
if(config.importMapping().containsKey(modelName)) {
continue;
}
//获取模板
Map modelTemplate = (Map) ((List) models.get("models")).get(0);
if (isJavaCodegen(config.getName())) {
// 特殊处理java别名
if (modelTemplate != null && modelTemplate.containsKey("model")) {
CodegenModel codegenModel = (CodegenModel) modelTemplate.get("model");
Map vendorExtensions = codegenModel.getVendorExtensions();
boolean isAlias = false;
if (vendorExtensions.get(CodegenConstants.IS_ALIAS_EXT_NAME) != null) {
isAlias = Boolean.parseBoolean(vendorExtensions.get(CodegenConstants.IS_ALIAS_EXT_NAME).toString());
}
if (isAlias) {
continue;
}
}
}
allModels.add(modelTemplate);
for (String templateName : config.modelTemplateFiles().keySet()) {
String suffix = config.modelTemplateFiles().get(templateName);
String filename = config.modelFileFolder() + File.separator + config.toModelFilename(modelName) + suffix;
if (!config.shouldOverwrite(filename)) {
LOGGER.info("Skipped overwriting " + filename);
continue;
}
//根据模板生成代码
File written = processTemplateToFile(models, templateName, filename);
if(written != null) {
files.add(written);
}
}
if(generateModelTests) {
//生成测试代码
generateModelTests(files, models, modelName);
}
if(generateModelDocumentation) {
// 生成doc
generateModelDocumentation(files, models, modelName);
}
} catch (Exception e) {
throw new RuntimeException("Could not generate model '" + modelName + "'", e);
}
}
......
}
2.生成apis
private void generateApis(List files, List allOperations, List allModels) {
if (!generateApis) {
return;
}
boolean hasModel = true;
if (allModels == null || allModels.isEmpty()) {
hasModel = false;
}
//获取所有整理过的路径信息
Map> paths = processPaths(this.openAPI.getPaths());
Set apisToGenerate = null;
String apiNames = System.getProperty("apis");
if(apiNames != null && !apiNames.isEmpty()) {
apisToGenerate = new HashSet(Arrays.asList(apiNames.split(",")));
}
if(apisToGenerate != null && !apisToGenerate.isEmpty()) {
Map> updatedPaths = new TreeMap<>();
for(String m : paths.keySet()) {
if(apisToGenerate.contains(m)) {
updatedPaths.put(m, paths.get(m));
}
}
paths = updatedPaths;
}
//生成每个api类
for (String tag : paths.keySet()) {
try {
List ops = paths.get(tag);
Collections.sort(ops, new Comparator() {
@Override
public int compare(CodegenOperation one, CodegenOperation another) {
return ObjectUtils.compare(one.operationId, another.operationId);
}
});
//获取api代码所需要的所有信息
Map operation = processOperations(config, tag, ops, allModels);
//路径对应OpenAPI的server的url
operation.put("basePath", basePath);
//没有host的路径
operation.put("basePathWithoutHost", basePathWithoutHost);
operation.put("contextPath", contextPath);
//标签名字,用于关联path(operation)
operation.put("baseName", tag);
//model包路径
operation.put("modelPackage", config.modelPackage());
operation.putAll(config.additionalProperties());
//类名 toApiName会生成驼峰格式的类名
operation.put("classname", config.toApiName(tag));
operation.put("classVarName", config.toApiVarName(tag));
operation.put("importPath", config.toApiImport(tag));
//类的文件名
operation.put("classFilename", config.toApiFilename(tag));
//额外的信息(可以包含自定义信息)
if(!config.vendorExtensions().isEmpty()) {
operation.put("vendorExtensions", config.vendorExtensions());
}
// Pass sortParamsByRequiredFlag through to the Mustache template...
boolean sortParamsByRequiredFlag = true;
if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
sortParamsByRequiredFlag = Boolean.valueOf(this.config.additionalProperties().get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString());
}
operation.put("sortParamsByRequiredFlag", sortParamsByRequiredFlag);
operation.put("hasModel", hasModel);
allOperations.add(new HashMap<>(operation));
for (int i = 0; i < allOperations.size(); i++) {
Map oo = (Map) allOperations.get(i);
if (i < (allOperations.size() - 1)) {
oo.put("hasMore", "true");
}
}
for (String templateName : config.apiTemplateFiles().keySet()) {
String filename = config.apiFilename(templateName, tag);
if (!config.shouldOverwrite(filename) && new File(filename).exists()) {
LOGGER.info("Skipped overwriting " + filename);
continue;
}
//根据模板生成代码
File written = processTemplateToFile(operation, templateName, filename);
if(written != null) {
files.add(written);
}
}
if(generateApiTests) {
// 生成api测试文件
for (String templateName : config.apiTestTemplateFiles().keySet()) {
String filename = config.apiTestFilename(templateName, tag);
// do not overwrite test file that already exists
if (new File(filename).exists()) {
LOGGER.info("File exists. Skipped overwriting " + filename);
continue;
}
File written = processTemplateToFile(operation, templateName, filename);
if (written != null) {
files.add(written);
}
}
}
if(generateApiDocumentation) {
// 生成api doc
for (String templateName : config.apiDocTemplateFiles().keySet()) {
String filename = config.apiDocFilename(templateName, tag);
if (!config.shouldOverwrite(filename) && new File(filename).exists()) {
LOGGER.info("Skipped overwriting " + filename);
continue;
}
File written = processTemplateToFile(operation, templateName, filename);
if (written != null) {
files.add(written);
}
}
}
} catch (Exception e) {
throw new RuntimeException("Could not generate api file for '" + tag + "'", e);
}
}
......
}
3.生成支持文件
private void generateSupportingFiles(List files, Map bundle) {
if (!generateSupportingFiles) {
return;
}
Set supportingFilesToGenerate = null;
String supportingFiles = System.getProperty(CodegenConstants.SUPPORTING_FILES);
boolean generateAll = false;
if (supportingFiles != null && supportingFiles.equalsIgnoreCase("true")) {
generateAll = true;
} else if (supportingFiles != null && !supportingFiles.isEmpty()) {
supportingFilesToGenerate = new HashSet<>(Arrays.asList(supportingFiles.split(",")));
}
for (SupportingFile support : config.supportingFiles()) {
try {
//生成文件和模板名字
......
//根据模板生成支持文件
if(ignoreProcessor.allowsFile(new File(outputFilename))) {
if (templateFile.endsWith("mustache")) {
String rendered = templateEngine.getRendered(templateFile, bundle);
writeToFile(outputFilename, rendered);
files.add(new File(outputFilename));
} else {
InputStream in = null;
try {
in = new FileInputStream(templateFile);
} catch (Exception e) {
// continue
}
if (in == null) {
in = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(templateFile));
}
File outputFile = new File(outputFilename);
OutputStream out = new FileOutputStream(outputFile, false);
if (in != null) {
LOGGER.info("writing file " + outputFile);
IOUtils.copy(in, out);
out.close();
} else {
LOGGER.warn("can't open " + templateFile + " for input");
}
files.add(outputFile);
}
} else {
LOGGER.info("Skipped generation of " + outputFilename + " due to rule in .swagger-codegen-ignore");
}
} catch (Exception e) {
throw new RuntimeException("Could not generate supporting file '" + support + "'", e);
}
}
//需要则生成 .swagger-codegen-ignore
final String swaggerCodegenIgnore = ".swagger-codegen-ignore";
String ignoreFileNameTarget = config.outputFolder() + File.separator + swaggerCodegenIgnore;
File ignoreFile = new File(ignoreFileNameTarget);
if (generateSwaggerMetadata && !ignoreFile.exists()) {
String ignoreFileNameSource = File.separator + config.getCommonTemplateDir() + File.separator + swaggerCodegenIgnore;
String ignoreFileContents = readResourceContents(ignoreFileNameSource);
try {
writeToFile(ignoreFileNameTarget, ignoreFileContents);
} catch (IOException e) {
throw new RuntimeException("Could not generate supporting file '" + swaggerCodegenIgnore + "'", e);
}
files.add(ignoreFile);
}
if(generateSwaggerMetadata) {
//生成swagger元数据
final String swaggerVersionMetadata = config.outputFolder() + File.separator + ".swagger-codegen" + File.separator + "VERSION";
File swaggerVersionMetadataFile = new File(swaggerVersionMetadata);
try {
writeToFile(swaggerVersionMetadata, ImplementationVersion.read());
files.add(swaggerVersionMetadataFile);
} catch (IOException e) {
throw new RuntimeException("Could not generate supporting file '" + swaggerVersionMetadata + "'", e);
}
}
}
1. aggregateByKey的运行机制
/**
* Aggregate the values of each key, using given combine functions and a neutral "zero value".
* This function can return a different result type
spark-sql是Spark bin目录下的一个可执行脚本,它的目的是通过这个脚本执行Hive的命令,即原来通过
hive>输入的指令可以通过spark-sql>输入的指令来完成。
spark-sql可以使用内置的Hive metadata-store,也可以使用已经独立安装的Hive的metadata store
关于Hive build into Spark
// Max value in Array
var arr = [1,2,3,5,3,2];Math.max.apply(null, arr); // 5
// Max value in Jaon Array
var arr = [{"x":"8/11/2009","y":0.026572007},{"x"
在使用XMlhttpRequest对象发送请求和响应之前,必须首先使用javaScript对象创建一个XMLHttpRquest对象。
var xmlhttp;
function getXMLHttpRequest(){
if(window.ActiveXObject){
xmlhttp:new ActiveXObject("Microsoft.XMLHTTP