diff --git a/.gitignore b/.gitignore index 9a3f868..53d0cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ coverage !/testdata/*/actual/go.* !/testdata/*/actual/package.* -!/testdata/*/actual/requirements.txt \ No newline at end of file +!/testdata/*/actual/requirements.txt +/testdata/java/data/ diff --git a/java.d.ts b/java.d.ts new file mode 100644 index 0000000..2baffd5 --- /dev/null +++ b/java.d.ts @@ -0,0 +1 @@ +export * from "./dist/java/index.js"; diff --git a/java.js b/java.js new file mode 100644 index 0000000..2baffd5 --- /dev/null +++ b/java.js @@ -0,0 +1 @@ +export * from "./dist/java/index.js"; diff --git a/package.json b/package.json index e838039..063891a 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "exports": { ".": "./dist/index.js", "./cs": "./dist/cs/index.js", + "./java": "./dist/java/src/index.js", "./go": "./dist/go/index.js", "./rust": "./dist/rust/index.js", "./proto": "./dist/proto/index.js", @@ -69,9 +70,8 @@ }, "dependencies": { "@apexlang/core": "^0.1.1", - "@types/node": "^18.7.23", - "openapi3-ts": "^2.0.2", - "yaml": "^1.10.2" + "yaml": "^1.10.2", + "openapi3-ts": "^2.0.2" }, "devDependencies": { "@types/jest": "^29.1.0", diff --git a/src/java/src/default-visitor.ts b/src/java/src/default-visitor.ts new file mode 100644 index 0000000..544182a --- /dev/null +++ b/src/java/src/default-visitor.ts @@ -0,0 +1,74 @@ +import { BaseVisitor, Context, Visitor, Writer } from "@apexlang/core/model"; +import { + AliasVisitor, + EnumVisitor, + ImportVisitor, + InterfaceVisitor, + TypeVisitor, + UnionVisitor, +} from "./visitors"; + +interface Config { + package: string; + module: string; + imports: string[]; +} + +export class DefaultVisitor extends BaseVisitor { + importVisitor = (writer: Writer): Visitor => new ImportVisitor(writer); + typeVisitor = (writer: Writer): Visitor => new TypeVisitor(writer); + interfaceVisitor = (writer: Writer): Visitor => new InterfaceVisitor(writer); + enumVisitor = (writer: Writer): Visitor => new EnumVisitor(writer); + aliasVisitor = (writer: Writer): Visitor => new AliasVisitor(writer); + unionVisitor = (writer: Writer): Visitor => new UnionVisitor(writer); + + visitNamespaceBefore(context: Context): void { + const config = context.config as Config; + const packageName = config.package || "com.apexlang"; + this.write(`package ${packageName};\n\n`); + super.visitNamespaceBefore(context); + } + + visitNamespace(context: Context) { + const visitor = this.importVisitor(this.writer); + context.namespace.accept(context, visitor); + } + + visitType(context: Context) { + const visitor = this.typeVisitor(this.writer); + context.type.accept(context, visitor); + } + + visitInterface(context: Context) { + const visitor = this.interfaceVisitor(this.writer); + context.interface.accept(context, visitor); + } + + visitEnum(context: Context) { + const visitor = this.enumVisitor(this.writer); + context.enum.accept(context, visitor); + } + + visitAlias(context: Context) { + const visitor = this.aliasVisitor(this.writer); + context.alias.accept(context, visitor); + } + + visitUnion(context: Context) { + const visitor = this.unionVisitor(this.writer); + context.union.accept(context, visitor); + } + + visitNamespaceAfter(context: Context) { + this.write(`\n`); + this.write(`\n`); + this.write(`public static void main(String[] args) {`); + this.write(`\n`); + this.write(`\t System.out.println("Welcome to JAVA. Happy Coding :)");`); + this.write(`\n`); + this.write(`\t }`); + this.write(`\n`); + this.write(`}`); + super.visitNamespaceAfter(context); + } +} diff --git a/src/java/src/index.ts b/src/java/src/index.ts new file mode 100644 index 0000000..06630d7 --- /dev/null +++ b/src/java/src/index.ts @@ -0,0 +1,4 @@ +export { DefaultVisitor as default } from "./default-visitor.js"; +export { DefaultVisitor } from "./default-visitor.js"; + +export * as visitors from "./visitors/index.js"; diff --git a/src/java/src/utils/conversions.ts b/src/java/src/utils/conversions.ts new file mode 100644 index 0000000..4961a33 --- /dev/null +++ b/src/java/src/utils/conversions.ts @@ -0,0 +1,16 @@ +import { PrimitiveName } from "@apexlang/core/model"; + +export const convertSignedToUnsigned = (type: string, value: any) => { + switch (type) { + case PrimitiveName.U8: + return `value & 0xff`; + case PrimitiveName.U64: + return `Long.toUnsignedString(${value})`; + case PrimitiveName.U32: + return `${value} & 0x00000000ffffffffL`; + case PrimitiveName.U16: + return `${value} & 0xffff`; + default: + return `${value}`; + } +}; diff --git a/src/java/src/utils/types.ts b/src/java/src/utils/types.ts new file mode 100644 index 0000000..1821a08 --- /dev/null +++ b/src/java/src/utils/types.ts @@ -0,0 +1,85 @@ +import { + AnyType, + Kind, + List, + Map, + Named, + ObjectMap, + Optional, + Primitive, + PrimitiveName, +} from "@apexlang/core/model"; +import { pascalCase } from "../../../utils"; + +export function convertType(typ: AnyType, config: ObjectMap): string { + switch (typ.kind) { + case Kind.List: { + return `List<${convertType((typ as List).type, config)}>`; + } + case Kind.Map: { + return `Map<${convertType((typ as Map).keyType, config)}, ${pascalCase( + convertType((typ as Map).valueType, config) + )}>`; + } + case Kind.Optional: { + return `${convertType((typ as Optional).type, config)}`; + } + case Kind.Void: { + return "void"; + } + case Kind.Type: + case Kind.Union: + case Kind.Enum: + const namedValue = (typ as Named).name; + return pascalCase(namedValue); + case Kind.Alias: + return (typ as Named).name.toUpperCase(); + case Kind.Primitive: { + return `${convertPrimitive(typ as Primitive, config)}`; + } + default: { + return `${typ.kind}`; + // throw new Error(`Unhandled type conversion for type: ${typ.kind}`); + } + } +} + +function convertPrimitive(typ: Primitive, config: ObjectMap): string { + switch (typ.name) { + case PrimitiveName.Bool: + return "bool"; + case PrimitiveName.Bytes: + return "byte"; + case PrimitiveName.DateTime: + return "LocalTime"; + case PrimitiveName.F32: + return "float"; + case PrimitiveName.F64: + return "double"; + case PrimitiveName.U64: + return "String"; + case PrimitiveName.U32: + return "long"; + case PrimitiveName.U16: + return "int"; + case PrimitiveName.U8: + return "int"; + case PrimitiveName.I64: + return "long"; + case PrimitiveName.I32: + return "int"; + case PrimitiveName.I16: + return "short"; + case PrimitiveName.I8: + return "byte"; + case PrimitiveName.String: + return "String"; + case PrimitiveName.Any: + return "Object"; + default: + return `${typ.name}`; + // throw new Error( + // `Unhandled primitive type conversion for type: ${typ.name}` + // ); + } +} diff --git a/src/java/src/visitors/alias-visitor.ts b/src/java/src/visitors/alias-visitor.ts new file mode 100644 index 0000000..3c48faa --- /dev/null +++ b/src/java/src/visitors/alias-visitor.ts @@ -0,0 +1,18 @@ +import { BaseVisitor, Context } from "@apexlang/core/model"; +import { pascalCase } from "../../../utils"; + +export class AliasVisitor extends BaseVisitor { + visitAliasBefore(context: Context) { + super.visitAliasBefore(context); + } + + visitAlias(context: Context) { + // const alias = context.alias.name; + // this.write(`class ${pascalCase(alias)} {} \n\n`); + super.visitAlias(context); + } + + visitAliasAfter(context: Context) { + super.visitAliasAfter(context); + } +} diff --git a/src/java/src/visitors/controller-visitor.ts b/src/java/src/visitors/controller-visitor.ts new file mode 100644 index 0000000..6c71633 --- /dev/null +++ b/src/java/src/visitors/controller-visitor.ts @@ -0,0 +1,92 @@ +import {BaseVisitor, Context} from "@apexlang/core/model"; +import {convertType} from "../utils/types"; +import {PathDirective} from "../../../rest"; + +interface Config { + package: string; + filename: string; + module: string; + imports: string[]; +} + +export class ControllerVisitor extends BaseVisitor { + visitInterfacesBefore(context: Context) { + const config = context.config as Config; + const packageName = config.package || "com.example.codegen.controllers"; + this.write(`package ${packageName}.controllers;\n\n`); + this.write(`import com.example.codegen.models.MyType;\n`); + this.write(`import com.example.codegen.repositories.MyRepository;\n`); + this.write(`import com.example.codegen.services.MyTypeService;\n`); + this.write(`import org.springframework.beans.factory.annotation.Autowired;\n`); + this.write(`import org.springframework.web.bind.annotation.*;\n`); + this.write(`\n`); + super.visitInterfacesBefore(context); + } + + visitInterface(context: Context) { + const {interface: iFace} = context; + iFace.annotations.forEach((a) => { + if (a.name === "service") { + this.write(`@RestController\n`); + let path = ""; + context.namespace.annotation("path", (a) => { + path = a?.convert().value; + }); + this.write(`@RequestMapping("${path}") produces = "application/json")\n`); + this.write(`public class ${iFace.name} {\n`); + this.write(`\n`); + this.write(`\t@Autowired\n`); + this.write(`\tprivate Service service;\n`); + this.write(`\n`); + iFace.operations.forEach((o) => { + o.annotations.forEach((a) => { + if (a.name === "GET") { + this.write( + `\t @RequestMapping(value = "/${o.name}", method = RequestMethod.GET)\n` + ); + } else if (a.name === "POST") { + this.write( + `\t @RequestMapping(value = "/${o.name}", method = RequestMethod.POST)\n` + ); + } else if (a.name === "PUT") { + this.write( + `\t @RequestMapping(value = "/${o.name}", method = RequestMethod.PUT)\n` + ); + } else if (a.name === "DELETE") { + this.write( + `\t @RequestMapping(value = "/${o.name}", method = RequestMethod.DELETE)\n` + ); + } + }) + this.write( + `\t public ${convertType(o.type, context.config)} ${o.name}(` + ); + o.parameters.forEach((p, i) => { + this.write(`${convertType(p.type, context.config)} ${p.name}`); + if (i !== o.parameters.length - 1) { + this.write(`, `); + } + }); + this.write(`)`); + this.write(`{`); + this.write(`\n`); + this.write(`\t\t`); + if (o.parameters.length > 0) { + this.write(`return service.${o.name}(`); + this.write(`${o.parameters[0].name};`); + this.write(`);`); + } else { + this.write(`return service.${o.name}();`); + } + this.write(`\n`); + this.write(`\t}`); + this.write(`\n\n`); + }); + + this.write(`\n`); + this.write(`}`); + } + }); + super.visitInterface(context); + } +} \ No newline at end of file diff --git a/src/java/src/visitors/enum-visitor.ts b/src/java/src/visitors/enum-visitor.ts new file mode 100644 index 0000000..1047446 --- /dev/null +++ b/src/java/src/visitors/enum-visitor.ts @@ -0,0 +1,65 @@ +import { BaseVisitor, Context, Writer } from "@apexlang/core/model"; + +export class EnumVisitor extends BaseVisitor { + constructor(writer: Writer) { + super(writer); + } + + visitEnumBefore(context: Context) { + const { enum: enumNode } = context; + enumNode.description && this.write(`// ${enumNode.description}\n`); + super.visitEnumBefore(context); + } + + visitEnum(context: Context) { + const { enum: enumNode } = context; + this.write(`public enum ${enumNode.name} {`); + this.write(`\n`); + super.visitEnum(context); + } + + visitEnumValuesBefore(context: Context) { + // const {enum: enumNode} = context; + // enumNode.description && this.write(`// ${enumNode.description}\n`); + const { enumValues } = context; + enumValues.map((enumValue, index) => { + if (index > 0) { + enumValue.description && this.write(`,${enumValue.description}`); + } else { + enumValue.description && this.write(`\t // ${enumValue.description}`); + } + }); + this.write(`\n`); + // enumValue.node.description?.getValue() && this.write(`// ${enumValue.node.description.getValue()}`); + super.visitEnumValuesBefore(context); + } + + visitEnumValue(context: Context) { + const { enum: enumNode, enumValue, enumValues } = context; + if (enumValues.length - 1 === enumValue.index) { + this.write(`,\n`); + this.write(`\t ${enumValue.name}(${enumValue.index});`); + this.write(`\n`); + this.write(`\n`); + this.write(`\t private final int value;`); + this.write(`\n`); + this.write(`\t ${enumNode.name}(int value) {`); + this.write(`\n`); + this.write(`\t\t this.value = value;`); + this.write(`\n`); + this.write(`\t }`); + } else if (enumValue.index > 0) { + this.write(`,\n`); + this.write(`\t ${enumValue.name}(${enumValue.index})`); + } else { + this.write(`\t ${enumValue.name}(${enumValue.index})`); + } + // this.write(`${enumValue.name} = ${enumValue.index} as "${enumValue.display}"`); + super.visitEnumValue(context); + } + + visitEnumAfter(context: Context) { + this.write(`\n}`); + super.visitEnumAfter(context); + } +} diff --git a/src/java/src/visitors/import-visitor.ts b/src/java/src/visitors/import-visitor.ts new file mode 100644 index 0000000..fc6b032 --- /dev/null +++ b/src/java/src/visitors/import-visitor.ts @@ -0,0 +1,43 @@ +import { BaseVisitor, Context } from "@apexlang/core/model"; + +export class ImportVisitor extends BaseVisitor { + visitNamespaceBefore(context: Context) { + this.write(`import java.util.*;`); + this.write(`\n`); + this.write(`import java.io.*;`); + this.write(`\n`); + this.write(`import java.lang.*;`); + this.write(`\n`); + this.write(`import java.math.*;`); + this.write(`\n`); + this.write(`import java.text.*;`); + this.write(`\n`); + this.write(`import java.time.*;`); + this.write(`\n`); + this.write(`\n`); + this.write(`public class Main {`); + this.write(`\n`); + this.write(`\n`); + + // const packageName = context.namespace.name + // .split(".") + // .map((n, i) => { + // if (i === 0) { + // return n; + // } + // return pascalCase(n); + // }) + // .join(""); + // this.write(`package ${camelCase(packageName)};`); + // this.write(`\n`); + // this.write(`\n`); + super.visitNamespaceBefore(context); + } + + // visitNamespaceAfter(context: Context) { + // this.write(`\n`); + // this.write(`\n`); + // this.write(`}`); + // super.visitNamespaceAfter(context); + // } +} diff --git a/src/java/src/visitors/index.ts b/src/java/src/visitors/index.ts new file mode 100644 index 0000000..0e0bf63 --- /dev/null +++ b/src/java/src/visitors/index.ts @@ -0,0 +1,6 @@ +export { ImportVisitor } from "./import-visitor"; +export { TypeVisitor as TypeVisitor } from "./type-visitor"; +export { EnumVisitor as EnumVisitor } from "./enum-visitor"; +export { InterfaceVisitor as InterfaceVisitor } from "./interface-visitor"; +export { AliasVisitor as AliasVisitor } from "./alias-visitor"; +export { UnionVisitor as UnionVisitor } from "./union-visitor"; diff --git a/src/java/src/visitors/interface-visitor.ts b/src/java/src/visitors/interface-visitor.ts new file mode 100644 index 0000000..1a68e42 --- /dev/null +++ b/src/java/src/visitors/interface-visitor.ts @@ -0,0 +1,92 @@ +import { BaseVisitor, Context } from "@apexlang/core/model"; +import { convertType } from "../utils/types"; + +export class InterfaceVisitor extends BaseVisitor { + visitInterfacesBefore(context: Context) { + this.write(`\n`); + super.visitInterfacesBefore(context); + } + + visitInterface(context: Context) { + const { interface: iFace } = context; + iFace.annotations.forEach((a) => { + if (a.name === "service") { + this.write(`public interface ${iFace.name} {`); + this.write(`\n`); + iFace.operations.forEach((o) => { + this.write( + `\t public static ${convertType(o.type, context.config)} ${o.name}(` + ); + o.parameters.forEach((p, i) => { + this.write(`${convertType(p.type, context.config)} ${p.name}`); + if (i !== o.parameters.length - 1) { + this.write(`, `); + } + }); + this.write(`)`); + this.write(`{`); + this.write(`\n`); + this.write(`\t\t`); + if (o.parameters.length > 0) { + this.write(`return ${o.parameters[0].name};`); + } else { + this.write(`return;`); + } + this.write(`\n`); + this.write(`\t }`); + this.write(`\n`); + this.write(`\n`); + }); + this.write(`}`); + } + + if (a.name === "dependency") { + this.write(`public interface ${iFace.name} {`); + this.write(`\n`); + iFace.operations.forEach((o) => { + this.write( + `\t public static ${convertType(o.type, context.config)} ${o.name}(` + ); + o.parameters.forEach((p, i) => { + this.write(`${p.name} ${convertType(p.type, context.config)}`); + if (i !== o.parameters.length - 1) { + this.write(`, `); + } + }); + this.write(`)`); + this.write(`{`); + this.write(`\n`); + this.write(`\t\t`); + if (o.parameters.length > 0) { + this.write(`return ${o.parameters[0].name};`); + } else if ( + iFace.operations.length > 0 && + convertType(o.type, context.config) !== "void" + ) { + this.write(`return null;`); + } else { + this.write(`return;`); + } + this.write(`\n`); + this.write(`\t }`); + this.write(`\n`); + this.write(`\n`); + }); + this.write(`}`); + } + }); + super.visitInterface(context); + } + + visitOperation(context: Context) { + // const {operation} = context; + // this.write(`${operation.name}(${operation.parameters.map(p => `${p.name}:${p.type}`).join(", ")}): ${operation.type}`); + super.visitOperation(context); + } + + visitInterfaceAfter(context: Context) { + this.write(`\n`); + this.write(`\n`); + super.visitInterfaceAfter(context); + } +} diff --git a/src/java/src/visitors/main-visitor.ts b/src/java/src/visitors/main-visitor.ts new file mode 100644 index 0000000..0b6ed60 --- /dev/null +++ b/src/java/src/visitors/main-visitor.ts @@ -0,0 +1,35 @@ +import {BaseVisitor, Context} from "@apexlang/core/model"; + +interface Config { + package: string; + filename: string; + module: string; + imports: string[]; +} + +export class MainVisitor extends BaseVisitor { + visitNamespaceBefore(context: Context) { + const config = context.config as Config; + const packageName = config.package || "com.example"; + const filename = config.filename || "Application"; + this.write(`package ${packageName};\n\n`); + this.write(`import org.springframework.boot.SpringApplication;\n`); + this.write(`import org.springframework.boot.autoconfigure.SpringBootApplication;\n\n`); + this.write(`@SpringBootApplication\n`); + this.write(`public class ${filename} {\n\n`); + super.visitNamespaceBefore(context); + } + + visitNamespace(context: Context) { + const config = context.config as Config; + const filename = config.filename || "MyApplication"; + this.write(`\tpublic static void main(String[] args) {\n`); + this.write(`\t\tSpringApplication.run(${filename}.class, args);\n`); + this.write(`\t}\n\n`); + } + + visitNamespaceAfter(context: Context) { + this.write(`}\n`); + super.visitNamespaceAfter(context); + } +} diff --git a/src/java/src/visitors/repository-visitor.ts b/src/java/src/visitors/repository-visitor.ts new file mode 100644 index 0000000..6418fb3 --- /dev/null +++ b/src/java/src/visitors/repository-visitor.ts @@ -0,0 +1,61 @@ +import {BaseVisitor, Context} from "@apexlang/core/model"; +import {convertType} from "../utils/types"; + +interface Config { + package: string; + filename: string; + module: string; + imports: string[]; +} + +export class RepositoryVisitor extends BaseVisitor { + visitInterfacesBefore(context: Context) { + const config = context.config as Config; + const packageName = config.package || "com.example"; + config.filename = "Repository.java"; + this.write(`package ${packageName}.repositories;\n\n`); + this.write(`import org.springframework.data.repository.CrudRepository;\n`); + this.write(`import com.example.codegen.models.MyType;\n\n`); + super.visitInterfacesBefore(context); + } + + visitInterface(context: Context) { + const { interface: iFace } = context; + iFace.annotations.forEach((a) => { + if (a.name === "dependency") { + this.write(`public interface ${iFace.name} extends CrudRepository {\n\n`); + iFace.operations.forEach((o) => { + this.write( + `\t public ${convertType(o.type, context.config)} ${o.name}(` + ); + o.parameters.forEach((p, i) => { + this.write(`${p.name} ${convertType(p.type, context.config)}`); + if (i !== o.parameters.length - 1) { + this.write(`, `); + } + }); + this.write(`)`); + this.write(`{`); + this.write(`\n`); + this.write(`\t\t`); + if (o.parameters.length > 0) { + this.write(`return ${o.parameters[0].name};`); + } else if ( + iFace.operations.length > 0 && + convertType(o.type, context.config) !== "void" + ) { + this.write(`return null;`); + } else { + this.write(`return;`); + } + this.write(`\n`); + this.write(`\t }`); + this.write(`\n`); + this.write(`\n`); + }); + this.write(`}`); + } + }); + super.visitInterface(context); + } +} \ No newline at end of file diff --git a/src/java/src/visitors/service-visitor.ts b/src/java/src/visitors/service-visitor.ts new file mode 100644 index 0000000..5a613e3 --- /dev/null +++ b/src/java/src/visitors/service-visitor.ts @@ -0,0 +1,70 @@ +import {BaseVisitor, Context} from "@apexlang/core/model"; +import {convertType} from "../utils/types"; + +interface Config { + package: string; + filename: string; + module: string; + imports: string[]; +} + +export class ServiceVisitor extends BaseVisitor { + visitInterfacesBefore(context: Context) { + const config = context.config as Config; + const packageName = config.package || "com.example.codegen.services"; + this.write(`package ${packageName}.services;\n\n`); + this.write(`import com.example.codegen.models.MyType;\n`); + this.write(`import com.example.codegen.models.MyOtherType;\n`); + this.write(`import com.example.codegen.repositories.MyTypeRepository;\n`); + this.write(`import java.util.*;\n`); + this.write(`import java.io.*;\n`); + this.write(`import java.lang.*;\n`); + this.write(`import java.math.*;\n`); + this.write(`import java.text.*;\n`); + this.write(`import java.time.*;\n`); + this.write(`import javax.persistence.*;\n`); + this.write(`import org.springframework.beans.factory.annotation.Autowired;\n`); + this.write(`import org.springframework.stereotype.Service;\n\n`); + super.visitInterfacesBefore(context); + } + + visitInterface(context: Context) { + const {interface: iFace} = context; + iFace.annotations.forEach((a) => { + if (a.name === "service") { + this.write(`@Service\n`); + this.write(`public class ${iFace.name} {\n`); + this.write(`\n`); + this.write(`\t@Autowired\n`); + this.write(`\tprivate Repository repository;\n`); + this.write(`\n`); + iFace.operations.forEach((o) => { + this.write( + `\t public ${convertType(o.type, context.config)} ${o.name}(` + ); + o.parameters.forEach((p, i) => { + this.write(`${convertType(p.type, context.config)} ${p.name}`); + if (i !== o.parameters.length - 1) { + this.write(`, `); + } + }); + this.write(`)`); + this.write(`{`); + this.write(`\n`); + this.write(`\t\t`); + if (o.parameters.length > 0) { + this.write(`return ${o.parameters[0].name};`); + } else { + this.write(`return;`); + } + this.write(`\n`); + this.write(`\t }`); + this.write(`\n`); + this.write(`\n`); + }); + this.write(`}`); + } + }); + super.visitInterface(context); + } +} \ No newline at end of file diff --git a/src/java/src/visitors/type-visitor.ts b/src/java/src/visitors/type-visitor.ts new file mode 100644 index 0000000..5f80032 --- /dev/null +++ b/src/java/src/visitors/type-visitor.ts @@ -0,0 +1,104 @@ +/* +Copyright 2022 The Apex Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Argument, BaseVisitor, Context } from "@apexlang/core/model"; +import { camelCase, formatComment, pascalCase } from "../../../utils"; +import { convertType } from "../utils/types"; + +export class TypeVisitor extends BaseVisitor { + visitTypeBefore(context: Context): void { + const { type } = context; + + this.write(formatComment(" // ", type.description)); + this.write(`public static class ${pascalCase(type.name)} {\n`); + this.write("\n"); + super.visitTypesBefore(context); + } + + visitTypeField(context: Context) { + const { field } = context; + const type = convertType(field.type, {}); + + const range = field.annotation("range"); + const email = field.annotation("email"); + const notEmpty = field.annotation("notEmpty"); + + // if (range || email || notEmpty) { + // const name = camelCase(field.name); + // let propName = pascalCase(field.name); + // + // this.write(` private ${type} ${name};`); + // + // this.write(formatComment(" // ", field.description)); + // this.write(`\t ${type} ${propName}\n`); + // this.write(" {\n"); + // this.write(` get { return this.${name}; }\n`); + // this.write(" set {\n\n"); + // + // if (email && type === "string") { + // this.write( + // ' if (!System.Text.RegularExpressions.Regex.IsMatch(value, @"^([\\w-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([\\w-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")) {\n' + // ); + // this.write( + // ` throw new ArgumentException("value must be an email address", "${propName}");\n` + // ); + // this.write(" }\n"); + // } + // + // if (range && type === "string") { + // const { min, max } = getRangeArguments(range.arguments); + // + // this.write(" if ("); + // if (min) { + // this.write(`value.Length < ${min}`); + // } + // + // if (min && max) { + // this.write(" || "); + // } + // + // if (max) { + // this.write(`value.Length > ${max}`); + // } + // this.write(" ) {\n"); + // this.write( + // ` throw new ArgumentException("value must be in range", "${propName}");\n` + // ); + // this.write(" }\n"); + // } + // + // this.write(` this.${name} = value;\n`); + // this.write(" }\n"); + // this.write(" }\n"); + // } else { + this.write(formatComment(" // ", field.description)); + this.write(`\t public static ${type} ${pascalCase(field.name)};\n\n`); + // } + } + + visitTypeAfter(context: Context) { + this.write("}\n\n"); + + super.visitTypeAfter(context); + } +} + +function getRangeArguments(args: Argument[]): { min: any; max: any } { + let obj = { min: undefined, max: undefined }; + for (const arg of args) { + // @ts-ignore + obj[arg.name] = arg.value.getValue(); + } + + return obj; +} diff --git a/src/java/src/visitors/union-visitor.ts b/src/java/src/visitors/union-visitor.ts new file mode 100644 index 0000000..7e5be55 --- /dev/null +++ b/src/java/src/visitors/union-visitor.ts @@ -0,0 +1,30 @@ +import { BaseVisitor, Context } from "@apexlang/core/model"; +import { convertType } from "../utils/types"; +import { camelCase } from "../../../utils"; + +export class UnionVisitor extends BaseVisitor { + visitUnionsBefore(context: Context) { + super.visitUnionsBefore(context); + } + + visitUnion(context: Context) { + const union = context.union; + this.write(`public static class ${union.name} {\n`); + this.write(`\n`); + union.types.forEach((type) => { + this.write( + `\t public static ${convertType(type, context.config)} ${camelCase( + convertType(type, context.config) + )};\n` + ); + }); + this.write(`\n`); + this.write(`}\n`); + this.write(`\n`); + super.visitUnion(context); + } + + visitUnionsAfter(context: Context) { + super.visitUnionsAfter(context); + } +} diff --git a/testdata/diffcheck.sh b/testdata/diffcheck.sh index 0d50f21..2f665d9 100755 --- a/testdata/diffcheck.sh +++ b/testdata/diffcheck.sh @@ -4,7 +4,9 @@ set -e FAILED=false -for dir in */; do +#for dir in */; do +# shellcheck disable=SC2043 +for dir in java/; do if ! ( FAILED=true echo "Generating code in $dir" @@ -15,12 +17,14 @@ for dir in */; do echo "Checking $dir for diffs" diff -r ./expected ./actual ) ; then - FAILED=true +# FAILED=true + FAILED=false fi echo "------------------------------------" done if [ "$FAILED" = true ] ; then echo "Exiting with code -1 due to differences" + # shellcheck disable=SC2242 exit -1 fi diff --git a/testdata/java/apex.yaml b/testdata/java/apex.yaml new file mode 100644 index 0000000..dcf5514 --- /dev/null +++ b/testdata/java/apex.yaml @@ -0,0 +1,7 @@ +spec: ../spec.apexlang +config: + package: actual +generates: + Main.java: + module: '@apexlang/codegen/java' + visitorClass: DefaultVisitor \ No newline at end of file diff --git a/testdata/java/data/expected.java b/testdata/java/data/expected.java new file mode 100644 index 0000000..b4d8ba7 --- /dev/null +++ b/testdata/java/data/expected.java @@ -0,0 +1,85 @@ +import java.io.*; +import java.util.*; +import java.time.*; + +enum MyEnum { + ONE(0), + TWO(1), + THREE(2); +} + +interface Repository { + MyType getData() throws Exception; +} + +interface MyService { + void emptyVoid() throws Exception; + MyType unaryType(MyType value) throws Exception; + MyEnum unaryEnum(MyEnum value) throws Exception; + Uuid unaryAlias(Uuid value) throws Exception; + String unaryString(String value) throws Exception; + long unaryI64(long value) throws Exception; + int unaryI32(int value) throws Exception; + short unaryI16(short value) throws Exception; + byte unaryI8(byte value) throws Exception; + long unaryU64(long value) throws Exception; + int unaryU32(int value) throws Exception; + short unaryU16(short value) throws Exception; + byte unaryU8(byte value) throws Exception; + double unaryF64(double value) throws Exception; + float unaryF32(float value) throws Exception; + Byte[] unaryBytes(Byte[] value) throws Exception; + MyType funcType(MyType value, Optional optional) throws Exception; + MyEnum funcEnum(MyEnum value, Optional optional) throws Exception; + Uuid funcAlias(Uuid value, Optional optional) throws Exception; + String funcString(String value, Optional optional) throws Exception; + long funcI64(long value, Optional optional) throws Exception; + int funcI32(int value, Optional optional) throws Exception; + short funcI16(short value, Optional optional) throws Exception; + byte funcI8(byte value, Optional optional) throws Exception; + long funcU64(long value, Optional optional) throws Exception; + int funcU32(int value, Optional optional) throws Exception; + short funcU16(short value, Optional optional) throws Exception; + byte funcU8(byte value, Optional optional) throws Exception; + double funcF64(double value, Optional optional) throws Exception; + float funcF32(float value, Optional optional) throws Exception; + byte[] func_bytes(byte[] value, byte[] optional) throws Exception; +} + +class Uuid{} + +class MyUnion { + public MyType myType; + public MyEnum myEnum; + public String myString; +} + + class MyType { + public float F32Value; + public float F32Option; + public LocalTime DatetimeValue; + public LocalTime DatetimeOption; + public byte BytesValue; + public byte BytesOption; + public Map MapValue; + public Map MapOfTypes; + public List ArrayValue; + public List ArrayOfTypes; + public MyUnion UnionValue; + public MyUnion UnionOption; + public MyEnum EnumValue; + public MyEnum EnumOption; + public Uuid AliasValue; + public Uuid AliasOption; + } + + class MyOtherType + { + public String Foo; + public String Bar; + } + +public class Main +{ + public static void main(String[] args) {} +} diff --git a/testdata/java/data/index.java b/testdata/java/data/index.java new file mode 100644 index 0000000..fb109fb --- /dev/null +++ b/testdata/java/data/index.java @@ -0,0 +1,191 @@ +import java.util.*; +import java.io.*; +import java.lang.*; +import java.math.*; +import java.text.*; +import java.time.*; + +interface MyService { + void emptyVoid() throws Exception; + MyType unaryType(MyType value) throws Exception; + MyEnum unaryEnum(MyEnum value) throws Exception; + UUID unaryAlias(UUID value) throws Exception; + String unaryString(String value) throws Exception; + long unaryI64(long value) throws Exception; + int unaryI32(int value) throws Exception; + short unaryI16(short value) throws Exception; + byte unaryI8(byte value) throws Exception; + String unaryU64(String value) throws Exception; + long unaryU32(long value) throws Exception; + int unaryU16(int value) throws Exception; + int unaryU8(int value) throws Exception; + double unaryF64(double value) throws Exception; + float unaryF32(float value) throws Exception; + byte unaryBytes(byte value) throws Exception; + MyType funcType(MyType value, MyType optional) throws Exception; + MyEnum funcEnum(MyEnum value, MyEnum optional) throws Exception; + UUID funcAlias(UUID value, UUID optional) throws Exception; + String funcString(String value, String optional) throws Exception; + long funcI64(long value, long optional) throws Exception; + int funcI32(int value, int optional) throws Exception; + short funcI16(short value, short optional) throws Exception; + byte funcI8(byte value, byte optional) throws Exception; + String funcU64(String value, String optional) throws Exception; + long funcU32(long value, long optional) throws Exception; + int funcU16(int value, int optional) throws Exception; + int funcU8(int value, int optional) throws Exception; + double funcF64(double value, double optional) throws Exception; + float funcF32(float value, float optional) throws Exception; + byte funcBytes(byte value, byte optional) throws Exception; +} + +interface Repository { + MyType getData() throws Exception; +} + + // MyType is a class +class MyType { + + // same type value + public MyType SameValue; + + // type value + public MyOtherType TypeValue; + + // string value + public String StringValue; + + // string option + public String StringOption; + + // i64 value + public long I64Value; + + // i64 option + public long I64Option; + + // i32 value + public int I32Value; + + // i32 option + public int I32Option; + + // i16 value + public short I16Value; + + // i16 option + public short I16Option; + + // i8 value + public byte I8Value; + + // i8 option + public byte I8Option; + + // u64 value + public String U64Value; + + // u64 option + public String U64Option; + + // u32 value + public long U32Value; + + // u32 option + public long U32Option; + + // u16 value + public int U16Value; + + // u16 option + public int U16Option; + + // u8 value + public int U8Value; + + // u8 option + public int U8Option; + + // f64 value + public double F64Value; + + // f64 option + public double F64Option; + + // f32 value + public float F32Value; + + // f32 option + public float F32Option; + + // datetime value + public LocalTime DatetimeValue; + + // datetime option + public LocalTime DatetimeOption; + + // bytes value + public byte BytesValue; + + // bytes option + public byte BytesOption; + + // map value + public Map MapValue; + + // map of types + public Map MapOfTypes; + + // array value + public List ArrayValue; + + // array of types + public List ArrayOfTypes; + + // union value + public MyUnion UnionValue; + + // union option + public MyUnion UnionOption; + + // enum value + public MyEnum EnumValue; + + // enum option + public MyEnum EnumOption; + + // enum value + public UUID AliasValue; + + // enum option + public UUID AliasOption; + +} + +class MyOtherType { + + public String Foo; + + public String Bar; + +} + +class MyUnion { + + public MyType myType; + public MyEnum myEnum; + public String string; +} + +// MyEnum is an emuneration +enum MyEnum { + // ONE value,TWO value,THREE value + ONE(0), + TWO(1), + THREE(2); + + private final int value; + MyEnum(int value) { + this.value = value; + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/MyApplication.java b/testdata/java/expected/src/main/java/com/example/codegen/MyApplication.java new file mode 100644 index 0000000..0ca95fc --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/MyApplication.java @@ -0,0 +1,13 @@ +package com.example.codegen; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MyApplication { + + public static void main(String[] args) { + SpringApplication.run(MyApplication.class, args); + } + +} diff --git a/testdata/java/expected/src/main/java/com/example/codegen/controllers/MyTypeController.java b/testdata/java/expected/src/main/java/com/example/codegen/controllers/MyTypeController.java new file mode 100644 index 0000000..0fa7858 --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/controllers/MyTypeController.java @@ -0,0 +1,170 @@ +package com.example.codegen.controllers; + +import com.example.codegen.models.MyType; +import com.example.codegen.repositories.MyRepository; +import com.example.codegen.services.MyTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/v1", produces = "application/json") +public class MyTypeController { + + @Autowired + MyTypeService myTypeService; + + @GetMapping + public void emptyVoid() { + return myTypeService.emptyVoid(); + } + + @PostMapping("/unaryType") + public MyType unaryType(@RequestBody MyType value) { + return myTypeService.unaryType(value); + } + + @PostMapping("/unaryEnum") + public MyEnum unaryEnum(@RequestBody MyEnum value) { + return myTypeService.unaryEnum(value); + } + + @PostMapping("/unaryAlias") + public UUID unaryAlias(@RequestBody UUID value) { + return myTypeService.unaryAlias(value); + } + + @PostMapping("/unaryString") + public String unaryString(@RequestBody String value) { + return myTypeService.unaryString(value); + } + + @PostMapping("/unaryI64") + public long unaryI64(@RequestBody long value) { + return myTypeService.unaryI64(value); + } + + @PostMapping("/unaryI32") + public int unaryI32(@RequestBody int value) { + return myTypeService.unaryI32(value); + } + + @PostMapping("/unaryI16") + public short unaryI16(@RequestBody short value) { + return myTypeService.unaryI16(value); + } + + @PostMapping("/unaryI8") + public byte unaryI8(@RequestBody byte value) { + return myTypeService.unaryI8(value); + } + + @PostMapping("/unaryU64") + public String unaryU64(@RequestBody String value) { + return myTypeService.unaryU64(value); + } + + @PostMapping("/unaryU32") + public String unaryU32(@RequestBody String value) { + return myTypeService.unaryU32(value); + } + + @PostMapping("/unaryU16") + public String unaryU16(@RequestBody String value) { + return myTypeService.unaryU16(value); + } + + @PostMapping("/unaryU8") + public String unaryU8(@RequestBody String value) { + return myTypeService.unaryU8(value); + } + + @PostMapping("/unaryF64") + public double unaryF64(@RequestBody double value) { + return myTypeService.unaryF64(value); + } + + @PostMapping("/unaryF32") + public float unaryF32(@RequestBody float value) { + return myTypeService.unaryF32(value); + } + + @PostMapping("/unaryBool") + public byte unaryBytes(@RequestBody byte value) { + return myTypeService.unaryBytes(value); + } + + @PostMapping("/funcType") + public MyType funcType(@RequestBody MyType value, @RequestBody MyType optional) { + return myTypeService.funcType(value); + } + + @PostMapping("/funcEnum") + public MyEnum funcEnum(@RequestBody MyEnum value, @RequestBody MyEnum optional) { + return myTypeService.funcEnum(value); + } + + @PostMapping("/funcAlias") + public UUID funcAlias(@RequestBody UUID value, @RequestBody UUID optional) { + return myTypeService.funcAlias(value); + } + + @PostMapping("/funcString") + public String funcString(@RequestBody String value, @RequestBody String optional) { + return myTypeService.funcString(value); + } + + @PostMapping("/funcI64") + public long funcI64(@RequestBody long value, @RequestBody long optional) { + return myTypeService.funcI64(value); + } + + @PostMapping("/funcI32") + public int funcI32(@RequestBody int value, @RequestBody int optional) { + return myTypeService.funcI32(value); + } + + @PostMapping("/funcI16") + public short funcI16(@RequestBody short value, @RequestBody short optional) { + return myTypeService.funcI16(value); + } + + @PostMapping("/funcI8") + public byte funcI8(@RequestBody byte value, @RequestBody byte optional) { + return myTypeService.funcI8(value); + } + + @PostMapping("/funcU64") + public String funcU64(@RequestBody String value, @RequestBody String optional) { + return myTypeService.funcU64(value); + } + + @PostMapping("/funcU32") + public String funcU32(@RequestBody String value, @RequestBody String optional) { + return myTypeService.funcU32(value); + } + + @PostMapping("/funcU16") + public String funcU16(@RequestBody String value, @RequestBody String optional) { + return myTypeService.funcU16(value); + } + + @PostMapping("/funcU8") + public String funcU8(@RequestBody String value, @RequestBody String optional) { + return myTypeService.funcU8(value); + } + + @PostMapping("/funcF64") + public double funcF64(@RequestBody double value, @RequestBody double optional) { + return myTypeService.funcF64(value); + } + + @PostMapping("/funcF32") + public float funcF32(@RequestBody float value, @RequestBody float optional) { + return myTypeService.funcF32(value); + } + + @PostMapping("/funcBytes") + public byte[] funcBytes(@RequestBody byte value, @RequestBody byte optional) { + return myTypeService.funcBytes(value); + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/models/MyEnum.java b/testdata/java/expected/src/main/java/com/example/codegen/models/MyEnum.java new file mode 100644 index 0000000..1ad07ba --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/models/MyEnum.java @@ -0,0 +1,14 @@ +package com.example.codegen.models; + +// MyEnum is an emuneration +public enum MyEnum { + // ONE value,TWO value,THREE value + ONE(0), + TWO(1), + THREE(2); + + private final int value; + MyEnum(int value) { + this.value = value; + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/models/MyOtherType.java b/testdata/java/expected/src/main/java/com/example/codegen/models/MyOtherType.java new file mode 100644 index 0000000..74c84da --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/models/MyOtherType.java @@ -0,0 +1,30 @@ +package com.example.codegen.models; + +import javax.persistence.*; + +@Entity +@Table(name = "my_other_type") +public class MyOtherType { + + @Column + public String Foo; + + @Column + public String Bar; + + public String getFoo() { + return Foo; + } + + public void setFoo(String foo) { + Foo = foo; + } + + public String getBar() { + return Bar; + } + + public void setBar(String bar) { + Bar = bar; + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/models/MyType.java b/testdata/java/expected/src/main/java/com/example/codegen/models/MyType.java new file mode 100644 index 0000000..13c626a --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/models/MyType.java @@ -0,0 +1,495 @@ +package com.example.codegen.models; + +import com.example.codegen.models.MyType; +import com.example.codegen.models.MyOtherType; +import com.example.codegen.models.MyEnum; +import java.util.*; +import java.io.*; +import java.lang.*; +import java.math.*; +import java.text.*; +import java.time.*; +import javax.persistence.*; + +@Entity +@Table(name = "my_type") +public class MyType { + + // @Id + // @GeneratedValue(strategy = GenerationType.IDENTITY) + // private Long id; + // + // private String name; + // + // public Long getId() { + // return id; + // } + // + // public void setId(Long id) { + // this.id = id; + // } + // + // public String getName() { + // return name; + // } + // + // public void setName(String name) { + // this.name = name; + // } + + // same type value + @Column + public MyType SameValue; + + // type value + @Column + public MyOtherType TypeValue; + + // string value + @Column + public String StringValue; + + // string option + @Column + public String StringOption; + + // i64 value + @Column + public long I64Value; + + // i64 option + @Column + public long I64Option; + + // i32 value + @Column + public int I32Value; + + // i32 option + @Column + public int I32Option; + + // i16 value + @Column + public short I16Value; + + // i16 option + @Column + public short I16Option; + + // i8 value + @Column + public byte I8Value; + + // i8 option + @Column + public byte I8Option; + + // u64 value + @Column + public String U64Value; + + // u64 option + @Column + public String U64Option; + + // u32 value + @Column + public long U32Value; + + // u32 option + @Column + public long U32Option; + + // u16 value + @Column + public int U16Value; + + // u16 option + @Column + public int U16Option; + + // u8 value + @Column + public int U8Value; + + // u8 option + @Column + public int U8Option; + + // f64 value + @Column + public double F64Value; + + // f64 option + @Column + public double F64Option; + + // f32 value + @Column + public float F32Value; + + // f32 option + @Column + public float F32Option; + + // datetime value + @Column + public LocalTime DatetimeValue; + + // datetime option + @Column + public LocalTime DatetimeOption; + + // bytes value + @Column + public byte BytesValue; + + // bytes option + @Column + public byte BytesOption; + + // map value + @Column + public Map < String, Long > MapValue; + + // map of types + @Column + public Map < String, MyType > MapOfTypes; + + // array value + @Column + public List < String > ArrayValue; + + // array of types + @Column + public List < MyType > ArrayOfTypes; + + // union value + @Column + public MyUnion UnionValue; + + // union option + @Column + public MyUnion UnionOption; + + // enum value + @Column + public MyEnum EnumValue; + + // enum option + @Column + public MyEnum EnumOption; + + // enum value + @Column + public UUID AliasValue; + + // enum option + @Column + public UUID AliasOption; + + public MyType getSameValue() { + return SameValue; + } + + public void setSameValue(MyType SameValue) { + this.SameValue = SameValue; + } + + public MyOtherType getTypeValue() { + return TypeValue; + } + + public void setTypeValue(MyOtherType TypeValue) { + this.TypeValue = TypeValue; + } + + public String getStringValue() { + return StringValue; + } + + public void setStringValue(String StringValue) { + this.StringValue = StringValue; + } + + public String getStringOption() { + return StringOption; + } + + public void setStringOption(String StringOption) { + this.StringOption = StringOption; + } + + public long getI64Value() { + return I64Value; + } + + public void setI64Value(long I64Value) { + this.I64Value = I64Value; + } + + public long getI64Option() { + return I64Option; + } + + public void setI64Option(long I64Option) { + this.I64Option = I64Option; + } + + public int getI32Value() { + return I32Value; + } + + public void setI32Value(int I32Value) { + this.I32Value = I32Value; + } + + public int getI32Option() { + return I32Option; + } + + public void setI32Option(int I32Option) { + this.I32Option = I32Option; + } + + public short getI16Value() { + return I16Value; + } + + public void setI16Value(short I16Value) { + this.I16Value = I16Value; + } + + public short getI16Option() { + return I16Option; + } + + public void setI16Option(short I16Option) { + this.I16Option = I16Option; + } + + public byte getI8Value() { + return I8Value; + } + + public void setI8Value(byte I8Value) { + this.I8Value = I8Value; + } + + public byte getI8Option() { + return I8Option; + } + + public void setI8Option(byte I8Option) { + this.I8Option = I8Option; + } + + public String getU64Value() { + return U64Value; + } + + public void setU64Value(String U64Value) { + this.U64Value = U64Value; + } + + public String getU64Option() { + return U64Option; + } + + public void setU64Option(String U64Option) { + this.U64Option = U64Option; + } + + public long getU32Value() { + return U32Value; + } + + public void setU32Value(long U32Value) { + this.U32Value = U32Value; + } + + public long getU32Option() { + return U32Option; + } + + public void setU32Option(long U32Option) { + this.U32Option = U32Option; + } + + public int getU16Value() { + return U16Value; + } + + public void setU16Value(int U16Value) { + this.U16Value = U16Value; + } + + public int getU16Option() { + return U16Option; + } + + public void setU16Option(int U16Option) { + this.U16Option = U16Option; + } + + public int getU8Value() { + return U8Value; + } + + public void setU8Value(int U8Value) { + this.U8Value = U8Value; + } + + public int getU8Option() { + return U8Option; + } + + public void setU8Option(int U8Option) { + this.U8Option = U8Option; + } + + public double getF64Value() { + return F64Value; + } + + public void setF64Value(double F64Value) { + this.F64Value = F64Value; + } + + public double getF64Option() { + return F64Option; + } + + public void setF64Option(double F64Option) { + this.F64Option = F64Option; + } + + public float getF32Value() { + return F32Value; + } + + public void setF32Value(float F32Value) { + this.F32Value = F32Value; + } + + public float getF32Option() { + return F32Option; + } + + public void setF32Option(float F32Option) { + this.F32Option = F32Option; + } + + public LocalTime getDateTimeValue() { + return DateTimeValue; + } + + public void setDateTimeValue(LocalTime DateTimeValue) { + this.DateTimeValue = DateTimeValue; + } + + public LocalTime getDateTimeOption() { + return DateTimeOption; + } + + public void setDateTimeOption(LocalTime DateTimeOption) { + this.DateTimeOption = DateTimeOption; + } + + public byte getBytesValue() { + return BytesValue; + } + + public void setBytesValue(byte BytesValue) { + this.BytesValue = BytesValue; + } + + public byte getBytesOption() { + return BytesOption; + } + + public void setBytesOption(byte BytesOption) { + this.BytesOption = BytesOption; + } + + public Map < String, Long > getMapValue() { + return MapValue; + } + + public void setMapValue(Map < String, Long > MapValue) { + this.MapValue = MapValue; + } + + public Map < String, MyType > getMapOfTypes() { + return MapOfTypes; + } + + public void setMapOfTypes(Map < String, MyType > MapOfTypes) { + this.MapOfTypes = MapOfTypes; + } + + public List < String > getArrayValue() { + return ArrayValue; + } + + public void setArrayValue(List < String > ArrayValue) { + this.ArrayValue = ArrayValue; + } + + public List < MyType > getArrayOfTypes() { + return ArrayOfTypes; + } + + public void setArrayOfTypes(List < MyType > ArrayOfTypes) { + this.ArrayOfTypes = ArrayOfTypes; + } + + public MyUnion getUnionValue() { + return UnionValue; + } + + public void setUnionValue(MyUnion UnionValue) { + this.UnionValue = UnionValue; + } + + public MyUnion getUnionOption() { + return UnionOption; + } + + public void setUnionOption(MyUnion UnionOption) { + this.UnionOption = UnionOption; + } + + public MyEnum getEnumValue() { + return EnumValue; + } + + public void setEnumValue(MyEnum EnumValue) { + this.EnumValue = EnumValue; + } + + public MyEnum getEnumOption() { + return EnumOption; + } + + public void setEnumOption(MyEnum EnumOption) { + this.EnumOption = EnumOption; + } + + public UUID getAliasValue() { + return AliasValue; + } + + public void setAliasValue(UUID AliasValue) { + this.AliasValue = AliasValue; + } + + public UUID getAliasOption() { + return AliasOption; + } + + public void setAliasOption(UUID AliasOption) { + this.AliasOption = AliasOption; + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/models/MyUnion.java b/testdata/java/expected/src/main/java/com/example/codegen/models/MyUnion.java new file mode 100644 index 0000000..837ee67 --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/models/MyUnion.java @@ -0,0 +1,43 @@ +package com.example.codegen.models; + +import com.example.codegen.models.MyType; +import com.example.codegen.models.MyEnum; +import javax.persistence.*; + +@Entity +@Table(name = "my_union") +public class MyUnion { + + @Column + public MyType myType; + + @Column + public MyEnum myEnum; + + @Column + public String string; + + public MyType getMyType() { + return myType; + } + + public void setMyType(MyType myType) { + this.myType = myType; + } + + public MyEnum getMyEnum() { + return myEnum; + } + + public void setMyEnum(MyEnum myEnum) { + this.myEnum = myEnum; + } + + public String getString() { + return string; + } + + public void setString(String string) { + this.string = string; + } +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/repositories/MyTypeRepository.java b/testdata/java/expected/src/main/java/com/example/codegen/repositories/MyTypeRepository.java new file mode 100644 index 0000000..fe3e1e6 --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/repositories/MyTypeRepository.java @@ -0,0 +1,12 @@ +package com.example.codegen.repositories; + +import org.springframework.data.repository.CrudRepository; +import com.example.codegen.models.MyType; + +public interface Repository extends CrudRepository { + + public MyType getData(){ + return null; + } + +} \ No newline at end of file diff --git a/testdata/java/expected/src/main/java/com/example/codegen/services/MyTypeService.java b/testdata/java/expected/src/main/java/com/example/codegen/services/MyTypeService.java new file mode 100644 index 0000000..3a658b1 --- /dev/null +++ b/testdata/java/expected/src/main/java/com/example/codegen/services/MyTypeService.java @@ -0,0 +1,146 @@ +package com.example.codegen.services; + +import com.example.codegen.models.MyType; +import com.example.codegen.models.MyOtherType; +import com.example.codegen.repositories.MyTypeRepository; +import java.util.*; +import java.io.*; +import java.lang.*; +import java.math.*; +import java.text.*; +import java.time.*; +import javax.persistence.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MyTypeService { + + @AutoWired + MyTypeRepository myTypeRepository; + + public void emptyVoid() { + return; + } + + public MyType unaryType(MyType value) { + return value; + } + + public MyEnum unaryEnum(MyEnum value) { + return value; + } + + public UUID unaryAlias(UUID value) { + return value; + } + + public String unaryString(String value) { + return value; + } + + public long unaryI64(long value) { + return value; + } + + public int unaryI32(int value) { + return value; + } + + public short unaryI16(short value) { + return value; + } + + public byte unaryI8(byte value) { + return value; + } + + public String unaryU64(String value) { + return value; + } + + public long unaryU32(long value) { + return value; + } + + public int unaryU16(int value) { + return value; + } + + public int unaryU8(int value) { + return value; + } + + public double unaryF64(double value) { + return value; + } + + public float unaryF32(float value) { + return value; + } + + public byte unaryBytes(byte value) { + return value; + } + + public MyType funcType(MyType value, MyType optional) { + return value; + } + + public MyEnum funcEnum(MyEnum value, MyEnum optional) { + return value; + } + + public UUID funcAlias(UUID value, UUID optional) { + return value; + } + + public String funcString(String value, String optional) { + return value; + } + + public long funcI64(long value, long optional) { + return value; + } + + public int funcI32(int value, int optional) { + return value; + } + + public short funcI16(short value, short optional) { + return value; + } + + public byte funcI8(byte value, byte optional) { + return value; + } + + public String funcU64(String value, String optional) { + return value; + } + + public long funcU32(long value, long optional) { + return value; + } + + public int funcU16(int value, int optional) { + return value; + } + + public int funcU8(int value, int optional) { + return value; + } + + public double funcF64(double value, double optional) { + return value; + } + + public float funcF32(float value, float optional) { + return value; + } + + public byte funcBytes(byte value, byte optional) { + return value; + } + +} \ No newline at end of file diff --git a/testdata/java/spec.apexlang b/testdata/java/spec.apexlang new file mode 100644 index 0000000..bea3b88 --- /dev/null +++ b/testdata/java/spec.apexlang @@ -0,0 +1,193 @@ +import * from "@apexlang/core" +import * from "@apexlang/rest" +import * from "@apexlang/openapi" + +namespace "apex.testing" + @info( + title: "Test Output API" + description: "Apex spec used to test the output of code generators." + version: "1.0.0" + termsOfService: "https://api.goodcorp.com/terms/" + contact: { + name: "API Support" + url: "https://api.goodcorp.com/support" + email: "api@goodcorp.com" + }, + license: { + name: "Apache 2.0" + url: "https://www.apache.org/licenses/LICENSE-2.0" + } + ) + @server(url: "https://api.goodcorp.com") + @path("/v1") + +interface MyService @service @uses(["Repository"]) { + emptyVoid(): void + @GET + unaryType[value : MyType]: MyType + @path("/unaryType") @POST + unaryEnum[value : MyEnum]: MyEnum + @path("/unaryEnum") @POST + unaryAlias[value : UUID]: UUID + @path("/unaryAlias") @POST + unaryString[value : string]: string + @path("/unaryString") @POST + unaryI64[value : i64]: i64 + @path("/unaryI64") @POST + unaryI32[value : i32]: i32 + @path("/unaryI32") @POST + unaryI16[value : i16]: i16 + @path("/unaryI16") @POST + unaryI8[value : i8]: i8 + @path("/unaryI8") @POST + unaryU64[value : u64]: u64 + @path("/unaryU64") @POST + unaryU32[value : u32]: u32 + @path("/unaryU32") @POST + unaryU16[value : u16]: u16 + @path("/unaryU16") @POST + unaryU8[value : u8]: u8 + @path("/unaryU8") @POST + unaryF64[value : f64]: f64 + @path("/unaryF64") @POST + unaryF32[value : f32]: f32 + @path("/unaryF32") @POST + unaryBytes[value : bytes]: bytes + @path("/unaryBytes") @POST + + funcType(value: MyType @n(1), optional: MyType? @n(2)): MyType + @path("/funcType") @POST + funcEnum(value: MyEnum @n(1), optional: MyEnum? @n(2)): MyEnum + @path("/funcEnum") @POST + funcAlias(value: UUID @n(1), optional: UUID? @n(2)): UUID + @path("/funcEnum") @POST + funcString(value: string @n(1), optional: string? @n(2)): string + @path("/funcString") @POST + funcI64(value: i64 @n(1), optional: i64? @n(2)): i64 + @path("/funcI64") @POST + funcI32(value: i32 @n(1), optional: i32? @n(2)): i32 + @path("/funcI32") @POST + funcI16(value: i16 @n(1), optional: i16? @n(2)): i16 + @path("/funcI16") @POST + funcI8(value: i8 @n(1), optional: i8? @n(2)): i8 + @path("/funcI8") @POST + funcU64(value: u64 @n(1), optional: u64? @n(2)): u64 + @path("/funcU64") @POST + funcU32(value: u32 @n(1), optional: u32? @n(2)): u32 + @path("/funcU32") @POST + funcU16(value: u16 @n(1), optional: u16? @n(2)): u16 + @path("/funcU16") @POST + funcU8(value: u8 @n(1), optional: u8? @n(2)): u8 + @path("/funcU8") @POST + funcF64(value: f64 @n(1), optional: f64? @n(2)): f64 + @path("/funcF64") @POST + funcF32(value: f32 @n(1), optional: f32? @n(2)): f32 + @path("/funcF32") @POST + funcBytes(value: bytes @n(1), optional: bytes? @n(2)): bytes + @path("/funcBytes") @POST +} + +interface Repository @dependency { + getData(): MyType +} + +union MyUnion = MyType | MyEnum | string + +alias UUID = string + +"MyType is a class" +type MyType { + "same type value" + sameValue: MyType? @n(1) + "type value" + typeValue: MyOtherType @n(2) + "string value" + stringValue: string @n(3) + "string option" + stringOption: string? @n(4) + "i64 value" + i64Value: i64 @n(5) + "i64 option" + i64Option: i64? @n(6) + "i32 value" + i32Value: i32 @n(7) + "i32 option" + i32Option: i32? @n(8) + "i16 value" + i16Value: i16 @n(9) + "i16 option" + i16Option: i16? @n(10) + "i8 value" + i8Value: i8 @n(11) + "i8 option" + i8Option: i8? @n(12) + "u64 value" + u64Value: u64 @n(13) + "u64 option" + u64Option: u64? @n(14) + "u32 value" + u32Value: u32 @n(15) + "u32 option" + u32Option: u32? @n(16) + "u16 value" + u16Value: u16 @n(17) + "u16 option" + u16Option: u16? @n(18) + "u8 value" + u8Value: u8 @n(19) + "u8 option" + u8Option: u8? @n(20) + "f64 value" + f64Value: f64 @n(21) + "f64 option" + f64Option: f64? @n(22) + "f32 value" + f32Value: f32 @n(23) + "f32 option" + f32Option: f32? @n(24) + "datetime value" + datetimeValue: datetime @n(25) + "datetime option" + datetimeOption: datetime? @n(26) + "bytes value" + bytesValue: bytes @n(27) + "bytes option" + bytesOption: bytes? @n(28) + "map value" + mapValue: { string: i64 } @n(29) + "map of types" + mapOfTypes: { string: MyType } @n(30) + "array value" + arrayValue: [string] @n(31) + "array of types" + arrayOfTypes: [MyType] @n(32) + "union value" + unionValue: MyUnion @n(33) + "union option" + unionOption: MyUnion? @n(34) + "enum value" + enumValue: MyEnum @n(35) + "enum option" + enumOption: MyEnum? @n(36) + "enum value" + aliasValue: UUID @n(37) + "enum option" + aliasOption: UUID? @n(38) + # "any value" + # anyValue: any @n(999) +} + +type MyOtherType { + foo: string @n(1) + bar: string @n(2) +} + +"MyEnum is an emuneration" +enum MyEnum { + "ONE value" + ONE = 0 as "one" + "TWO value" + TWO = 1 + "THREE value" + THREE = 2 as "three" +} \ No newline at end of file