UNPKG

@wuapi/generator

Version:
417 lines (413 loc) 16.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const essential_1 = require("@wuapi/essential"); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const ncp_1 = __importDefault(require("ncp")); const lodash_1 = __importDefault(require("lodash")); const brace_1 = require("./brace"); const plugin_base_1 = require("./plugin_base"); const dedent_1 = __importDefault(require("dedent")); /** * Java code plugin. */ class JavaPlugin extends plugin_base_1.BasePlugin { /** * Returns the description of this plugin. */ getDescription() { return { name: "java", abbreviation: "j", version: "1.0.0", description: "Generate Java code.", arguments: [ { tag: "getter", withValue: false, description: "Generate getter/setters of properties", }, { tag: "gradle", withValue: false, description: "Generate gradle project", }, { tag: "inc", withValue: false, description: "Increamental, NOT overriding old files (only work with 'gradle' mode)", }, ], }; } /** * Process gradle project. */ processGradle(project, outputDir, skip, next) { if (skip) { next(); return; } const srcDir = [__dirname, "..", "template", this.getName()].join(path_1.default.sep); const dstDir = [outputDir, this.getName()].join(path_1.default.sep); (0, ncp_1.default)(srcDir, dstDir, (error) => { if (error) { return console.error(error); } const map = { "{{project_name}}": project.name, "{{project_version}}": project.version, "{{project_package}}": project.targetPackage, }; this.rewriteFile([srcDir, "settings.gradle"].join(path_1.default.sep), [dstDir, "settings.gradle"].join(path_1.default.sep), map); this.rewriteFile([srcDir, "library", "build.gradle"].join(path_1.default.sep), [dstDir, "library", "build.gradle"].join(path_1.default.sep), map); next(); }); } /** * Start process the project, and generate code. */ process(project, outputDir, args) { if (args["gradle"] != undefined) { const javaDir = [outputDir, this.getName(), "library", "src", "main"].join(path_1.default.sep); fs_1.default.mkdirSync(javaDir, { recursive: true }); this.processGradle(project, outputDir, args["inc"] != undefined, () => { new JavaPlugin().process(project, javaDir, lodash_1.default.omit(args, ["gradle", "inc"])); }); return; } new JavaProcessor(this, project, outputDir, args).process(); } } exports.default = JavaPlugin; /** * The Java project processor */ class JavaProcessor extends plugin_base_1.ProjectProcessor { get useGetter() { return this.config['getter'] != undefined; } constructor(plugin, project, outputDir, config) { super(plugin, project, outputDir, config); this.packageDir = lodash_1.default.concat([this.rootDir], this.project.targetPackage.split('.')).join(path_1.default.sep); } /** * Write text into java file. * @param name The name of this file (without extension). * @param text The content of the file */ writeJavaFile(name, text) { const filePath = this.packageDir + path_1.default.sep + name + ".java"; const file = fs_1.default.openSync(filePath, 'w'); fs_1.default.writeFileSync(file, (0, dedent_1.default) ` package ${this.project.targetPackage}; import java.util.*; ` + '\n\n' + text); } /** * Write an entity. * @param pth The path to the entity. * @param entity The entity */ writeEntity(pth, entity) { const self = this; // function genericTypeName(type) { switch (type.type) { case "TBoolean": return "Boolean"; case "TInteger": return "Integer"; case "TLong": return "Long"; case "TID": return "Long"; case "TDouble": return "Double"; case "TString": return "String"; case "TURL": return "String"; case "TDateTime": return "Long"; case "TSSMap": return "HashMap<String, String>"; case "TEnum": return type.enu.name; case "TObject": return type.entity.name; case "TUnknown": return type.unknown; //case "TList" : return memberTypeName(type as $TList) case "TList": return `List<${genericTypeName(type.member)}>`; default: throw new Error(`Unknown generic type "${type.type}" in "${pth.module}/${pth.name}"`); } } // function generateFixedValue(name, f) { let value = ""; const prefix = self.useGetter ? "private" : "public"; switch (f.type.type) { case "TBoolean": value = `${f.fixedValue}`; break; case "TInteger": value = `${f.fixedValue}`; break; case "TLong": value = `${f.fixedValue}L`; break; case "TID": value = `${f.fixedValue}L`; break; case "TDouble": value = `${f.fixedValue}`; break; case "TString": value = `"${f.fixedValue}"`; break; case "TURL": value = `"${f.fixedValue}"`; break; case "TDateTime": value = `${f.fixedValue}`; break; default: throw Error(`Type "${f.type.type}" of Field "${name}" in "${pth.module}/${pth.name}" can NOT have fixed value!`); } return `${prefix} final ${genericTypeName(f.type)} ${name} = ${value};`; } // function generateOptionalValue(name, f) { const prefix = self.useGetter ? "private" : "public"; return `${prefix} ${genericTypeName(f.type)} ${name} = null;`; } // function generateDefaultValue(name, f) { let value = ""; const prefix = self.useGetter ? "private" : "public"; switch (f.type.type) { case "TBoolean": value = ""; break; case "TInteger": value = ""; break; case "TLong": value = ""; break; case "TID": value = ""; break; case "TDouble": value = ""; break; case "TString": value = "= \"\""; break; case "TURL": value = "= \"\""; break; case "TDateTime": value = ""; break; case "TSSMap": value = "= new HashMap<>()"; break; case "TObject": value = "= null"; break; case "TUnknown": value = "= null"; break; case "TList": value = "= new LinkedList<>()"; break; case "TEnum": { let fe = f.type; value = `= ${fe.enu.name}.${fe.enu.asEnumOf(self.project).firstName()}`; break; } default: throw Error(`Type "${f.type.type}" of Field "${name}" in "${pth.module}/${pth.name}" is invalid.`); } return `${prefix} ${genericTypeName(f.type)} ${name} ${value};`; } // function calcSuffix(extra) { let unsolved = entity.getGenericUnsolved(self.project); if (extra) { unsolved = lodash_1.default.concat(unsolved, [extra]); } return (unsolved.length > 0) ? `<${unsolved.join(", ")}>` : ""; } // function calcExtSuffix(extra) { let punsolved = entity.parent?.asEntityOf(self.project)?.getGenericUnsolved(self.project) ?? []; let unsolved = []; punsolved.forEach((name) => { let solved = entity.genericMap[name]; let item = (solved) ? genericTypeName(solved.type) : name; unsolved.push(item); }); if (extra) { unsolved = lodash_1.default.concat(unsolved, [extra]); } return (unsolved.length > 0) ? `<${unsolved.join(", ")}>` : ""; } // function generateField(b, name, f) { if (f.realname) { b(`@SerializedName("${f.realname}")`); } if (f.fixedValue) { b(generateFixedValue(name, f)); } else if (f.isOptional) { b(generateOptionalValue(name, f)); } else { b(generateDefaultValue(name, f)); } } // function generateGetterSetter(b, name, f) { const _name = lodash_1.default.camelCase(name); b.bra(`public ${genericTypeName(f.type)} get${_name}()`).add((b) => { b(`return ${name};`); }); b.bra(`public void set${_name}(${genericTypeName(f.type)} value)`).add((b) => { b(`${name} = value;`); }); } this.writeJavaFile(pth.name, (0, brace_1.flatBra)("").add((b) => { // b(toBlockComment(entity)) const prefix = (entity.isAbstract) ? "abstract" : ""; switch (entity.type) { //////////////////// // REQUEST //////////////////// case essential_1.$EntityType.REQUEST: { let resName = entity.response?.name; let pname = entity.parent?.name ?? "AbsReq"; let suffix = calcSuffix((entity.isAbstract) ? "R extends AbsRes" : undefined); let extSuf = calcExtSuffix((entity.isAbstract) ? "R" : (resName ?? undefined)); b.bra(`public ${prefix} class ${pth.name}${suffix} extends ${pname}${extSuf}`).add((b) => { if (!entity.isAbstract) { b((0, dedent_1.default) ` @Override public String obtainPath() { return "${entity.path}"; } @Override public String obtainMethod() { return ${entity.method ? `"${entity.method}"` : "null"}; } @Override public Class<? extends ${resName}> obtainResClass() { return ${resName}.class; } `); } // lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateField(b, name, f); }); b(""); if (this.useGetter) { lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateGetterSetter(b, name, f); }); } }); break; } //////////////////// // RESPONSE //////////////////// case essential_1.$EntityType.RESPONSE: { let pname = entity.parent?.name ?? "AbsRes"; let suffix = calcSuffix(); let extSuf = calcExtSuffix(); b.bra(`public ${prefix} class ${pth.name}${suffix} extends ${pname}${extSuf}`).add((b) => { // lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateField(b, name, f); }); b(""); if (this.useGetter) { lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateGetterSetter(b, name, f); }); } }); break; } //////////////////// // OBJECT //////////////////// case essential_1.$EntityType.OBJECT: { let extendString = (entity.parent) ? `extends ${entity.parent.name}` : ""; let suffix = calcSuffix(); let extSuf = calcExtSuffix(); b.bra(`public ${prefix} class ${pth.name}${suffix} ${extendString}${extSuf}`).add((b) => { // lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateField(b, name, f); }); b(""); if (this.useGetter) { lodash_1.default.forIn(entity.fieldsLocal, (f, name) => { generateGetterSetter(b, name, f); }); } }); break; } } }).toString()); } /** * Write an enumeration * @param pth The path to the enumeration * @param enu The enumeration. */ writeEnum(pth, enu) { this.writeJavaFile(pth.name, (0, brace_1.flatBra)("").add((b) => { // b(toBlockComment(enu)) b.bra(`public enum ${pth.name}`).add((b) => { enu.flat().forEach(({ name, item }) => { // b(toLineComment(item)) b(`${name}(${item.value}),`); }); b((0, dedent_1.default) ` ; private int value; private ${pth.name}(int value) { this.value = value; } public int getValue() { return value; } `); b.bra(`public static ${pth.name} find(int value)`).add((b) => { b.bra("switch(value)").add((b) => { enu.flat().forEach(({ name, item }) => { b(`case ${item.value}: return ${name};`); }); b("default: return null;"); }); }); }); }).toString()); } /** * Process the project. */ process() { fs_1.default.rmSync(this.rootDir, { recursive: true, force: true }); fs_1.default.mkdirSync(this.packageDir, { recursive: true }); this.writeJavaFile("AbsReq", (0, dedent_1.default) ` public abstract class AbsReq<R extends AbsRes> { public abstract String obtainPath(); public abstract String obtainMethod(); public abstract Class<? extends R> obtainResClass(); }`); this.writeJavaFile("AbsRes", (0, dedent_1.default) ` public abstract class AbsRes { }`); this.project.flatEntities().forEach(({ path, entity }) => { this.writeEntity(path, entity); }); this.project.flatEnums().forEach(({ path, enu }) => { this.writeEnum(path, enu); }); } }