Skip to content

Commit

Permalink
generating java-server service APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
tomsontom committed Oct 27, 2024
1 parent 972b2c6 commit a5c7f1f
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 58 deletions.
21 changes: 12 additions & 9 deletions dsl/src/cli/java-client-api/base-dto.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { CompositeGeneratorNode, NL, toString } from "langium/generate";

import { Artifact } from "../artifact-generator.js";
import { JavaClientAPIGeneratorConfig, toPath } from "../java-gen-utils.js";
import { generateCompilationUnit, JavaClientAPIGeneratorConfig, JavaImportsCollector, toPath } from "../java-gen-utils.js";

export function generateBaseDTO(artifactConfig: JavaClientAPIGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.dto`;

return {
name: 'BaseDTO.java',
content: toString(generateCompilationUnit(packageName, new JavaImportsCollector(packageName), generateBaseDTOContent())),
path: toPath(artifactConfig.targetFolder, packageName)
}
}

export function generateBaseDTOContent() {
const node = new CompositeGeneratorNode()
node.append('// Generated by RSD - Do not modify',NL)
node.append(`package ${packageName};`, NL, NL)
node.append(`public interface BaseDTO {`,NL)
node.indent( child => {
child.append(`public interface Builder {`, NL)
Expand All @@ -17,9 +24,5 @@ export function generateBaseDTO(artifactConfig: JavaClientAPIGeneratorConfig): A
child.append('}',NL)
});
node.append('}',NL)
return {
name: 'BaseDTO.java',
content: toString(node),
path: toPath(artifactConfig.targetFolder, packageName)
}
}
return node;
}
16 changes: 10 additions & 6 deletions dsl/src/cli/java-client-api/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaClientA
const importCollector = new JavaImportsCollector(packageName);
const fqn = importCollector.importType.bind(importCollector);


return {
name: `${t.name}DTO.java`,
content: toString(generateCompilationUnit(packageName, importCollector, generateUnionContent(t, artifactConfig, fqn))),
path: toPath(artifactConfig.targetFolder, packageName)
};
}

export function generateUnionContent(t: MResolvedUnionType, artifactConfig: JavaClientAPIGeneratorConfig, fqn: (type: string) => string) {
const node = new CompositeGeneratorNode();
node.append(`public interface ${t.name}DTO extends BaseDTO {`,NL)

Expand Down Expand Up @@ -73,10 +82,5 @@ export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaClientA
}

node.append('}',NL)

return {
name: `${t.name}DTO.java`,
content: toString(generateCompilationUnit(packageName, importCollector, node)),
path: toPath(artifactConfig.targetFolder, packageName)
};
return node;
}
15 changes: 13 additions & 2 deletions dsl/src/cli/java-gen-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ export type JavaRestClientJDKGeneratorConfig = ArtifactGenerationConfig & {
nativeTypeSubstitues?: Record<string, string>
}

export type JavaServerJakartaWSConfig = ArtifactGenerationConfig & {
export type JavaServerJakartaWSGeneratorConfig = ArtifactGenerationConfig & {
targetFolder: string
rootPackageName: string
nativeTypeSubstitues?: Record<string, string>
}

export type JavaServerGeneratorConfig = ArtifactGenerationConfig & {
targetFolder: string
rootPackageName: string
nativeTypeSubstitues?: Record<string, string>
Expand All @@ -82,7 +88,12 @@ export function isJavaRestClientJDKGeneratorConfig(config: ArtifactGeneratorConf
&& 'rootPackageName' in config && typeof config.rootPackageName === 'string';
}

export function isJavaServerJakartaWSConfig(config: ArtifactGeneratorConfig): config is JavaServerJakartaWSConfig {
export function isJavaServerJakartaWSConfig(config: ArtifactGeneratorConfig): config is JavaServerJakartaWSGeneratorConfig {
return 'targetFolder' in config && typeof config.targetFolder === 'string'
&& 'rootPackageName' in config && typeof config.rootPackageName === 'string';
}

export function isJavaServerConfig(config: ArtifactGeneratorConfig): config is JavaServerGeneratorConfig {
return 'targetFolder' in config && typeof config.targetFolder === 'string'
&& 'rootPackageName' in config && typeof config.rootPackageName === 'string';
}
Expand Down
4 changes: 2 additions & 2 deletions dsl/src/cli/java-server-jakarta-ws/enum.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CompositeGeneratorNode, NL, toString } from "langium/generate";

import { Artifact } from "../artifact-generator.js";
import { JavaServerJakartaWSConfig, toPath } from "../java-gen-utils.js";
import { JavaServerJakartaWSGeneratorConfig, toPath } from "../java-gen-utils.js";
import { MEnumType, MInlineEnumType } from "../model.js";

export function generateEnum(t: MEnumType, artifactConfig: JavaServerJakartaWSConfig): Artifact {
export function generateEnum(t: MEnumType, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.rest.dto`;

const node = new CompositeGeneratorNode()
Expand Down
4 changes: 2 additions & 2 deletions dsl/src/cli/java-server-jakarta-ws/generator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chalk from "chalk";
import { isMEnumType, isMRecordType, isMUnionType, MResolvedRSDModel, MResolvedUserType } from "../model.js";
import { Artifact, ArtifactGenerationConfig, ArtifactGeneratorConfig } from "../artifact-generator.js";
import { isJavaServerJakartaWSConfig, JavaServerJakartaWSConfig } from "../java-gen-utils.js";
import { isJavaServerJakartaWSConfig, JavaServerJakartaWSGeneratorConfig } from "../java-gen-utils.js";
import { isDefined } from "../util.js";
import { generateRecord } from "./record.js";
import { generateUnion } from "./union.js";
Expand All @@ -21,7 +21,7 @@ export function generate(model: MResolvedRSDModel, generatorConfig: ArtifactGene
return result;
}

function generateType(t: MResolvedUserType, artifactConfig: JavaServerJakartaWSConfig): Artifact | undefined {
function generateType(t: MResolvedUserType, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact | undefined {
if( isMEnumType(t) ) {

} else if( isMRecordType(t) ) {
Expand Down
8 changes: 4 additions & 4 deletions dsl/src/cli/java-server-jakarta-ws/record.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { CompositeGeneratorNode, NL, toString } from "langium/generate";
import { Artifact } from "../artifact-generator.js";
import { builtinToJavaType, generateCompilationUnit, JavaImportsCollector, JavaServerJakartaWSConfig, resolveObjectType, resolveType, toPath } from "../java-gen-utils.js";
import { builtinToJavaType, generateCompilationUnit, JavaImportsCollector, JavaServerJakartaWSGeneratorConfig, resolveObjectType, resolveType, toPath } from "../java-gen-utils.js";
import { allRecordProperties, isMInlineEnumType, isMKeyProperty, isMProperty, isMRevisionProperty, MResolvedRecordType } from "../model.js";
import { toFirstUpper } from "../util.js";
import { generateInlineEnum } from "./enum.js";

export function generateRecord(t: MResolvedRecordType, artifactConfig: JavaServerJakartaWSConfig): Artifact | undefined {
export function generateRecord(t: MResolvedRecordType, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact | undefined {
if( t.resolved.unions.length === 1 ) {
return undefined;
}
Expand All @@ -21,15 +21,15 @@ export function generateRecord(t: MResolvedRecordType, artifactConfig: JavaServe
};
}

export function generateRecordContent(t: MResolvedRecordType, artifactConfig: JavaServerJakartaWSConfig, fqn: (type: string) => string): CompositeGeneratorNode {
export function generateRecordContent(t: MResolvedRecordType, artifactConfig: JavaServerJakartaWSGeneratorConfig, fqn: (type: string) => string): CompositeGeneratorNode {
const node = new CompositeGeneratorNode();

const allProps = allRecordProperties(t);

node.append(`public record ${t.name}DTO(`,NL)
node.indent( param => {
allProps.forEach( (property, idx, arr) => {
const end = idx + 1 < arr.length ? ',' : ') {'
const end = idx + 1 < arr.length ? ',' : `) implements ${artifactConfig.rootPackageName}.service.dto.${t.name}DTO {`
if( isMKeyProperty(property) ) {
param.append(`${builtinToJavaType(property.type, fqn)} ${property.name}`, end, NL)
} else if( isMRevisionProperty(property) ) {
Expand Down
6 changes: 3 additions & 3 deletions dsl/src/cli/java-server-jakarta-ws/service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { CompositeGeneratorNode, NL, toString } from "langium/generate";
import { Artifact } from "../artifact-generator.js";
import { generateCompilationUnit, JavaImportsCollector, JavaRestClientJDKGeneratorConfig, toPath } from "../java-gen-utils.js";
import { generateCompilationUnit, JavaImportsCollector, JavaServerJakartaWSGeneratorConfig, toPath } from "../java-gen-utils.js";
import { MResolvedOperation, MResolvedService } from "../model.js";
import { toFirstUpper } from "../util.js";
import { toType } from "../java-client-api/shared.js";

export function generateService(s: MResolvedService, artifactConfig: JavaRestClientJDKGeneratorConfig): Artifact[] {
export function generateService(s: MResolvedService, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact[] {
const result : Artifact[] = [];
const serviceDTOs = s.operations
.filter( o => o.parameters.filter( p => p.meta?.rest?.source === undefined).length > 1 )
Expand All @@ -15,7 +15,7 @@ export function generateService(s: MResolvedService, artifactConfig: JavaRestCli
return result;
}

function generateServiceDTO(s: MResolvedService, o: MResolvedOperation, artifactConfig: JavaRestClientJDKGeneratorConfig): Artifact {
function generateServiceDTO(s: MResolvedService, o: MResolvedOperation, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.rest.dto`;

const importCollector = new JavaImportsCollector(packageName);
Expand Down
99 changes: 69 additions & 30 deletions dsl/src/cli/java-server-jakarta-ws/union.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { CompositeGeneratorNode, IndentNode, NL, toString } from "langium/generate";
import { Artifact } from "../artifact-generator.js";
import { builtinToJavaType, generateCompilationUnit, JavaImportsCollector, JavaServerJakartaWSConfig, resolveObjectType, resolveType, toPath } from "../java-gen-utils.js";
import { allRecordProperties, isMInlineEnumType, isMKeyProperty, isMProperty, isMRevisionProperty, MKeyProperty, MProperty, MResolvedRecordType, MResolvedUnionType, MRevisionProperty } from "../model.js";
import { generateInlineEnum } from "./enum.js";
import { builtinToJavaType, generateCompilationUnit, JavaImportsCollector, JavaServerJakartaWSGeneratorConfig, resolveObjectType, resolveType, toPath } from "../java-gen-utils.js";
import { allRecordProperties, isMKeyProperty, isMRevisionProperty, MKeyProperty, MProperty, MResolvedRecordType, MResolvedUnionType, MRevisionProperty } from "../model.js";
import { toFirstUpper } from "../util.js";

export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaServerJakartaWSConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.rest.dto!`;
export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaServerJakartaWSGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.rest.dto`;

const importCollector = new JavaImportsCollector(packageName);
const fqn = importCollector.importType.bind(importCollector);
Expand All @@ -25,22 +24,16 @@ export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaServerJ
} );

node.append('})',NL)
node.append(`public abstract class ${t.name}DTO {`,NL)
t.resolved.sharedProps
.filter(isMProperty)
.filter(p => p.variant === 'inline-enum')
.forEach( p => {
const inlineEnum = p.type;
if( isMInlineEnumType(inlineEnum) ) {
generateInlineEnum(inlineEnum, toFirstUpper(p.name), node)
}
});

node.append(`public abstract class ${t.name}DTO implements ${artifactConfig.rootPackageName}.service.dto.${t.name}DTO {`,NL)

node.indent( child => {
t.resolved.sharedProps.forEach( p => generateProperty(child, p, artifactConfig, fqn) )
})

node.indent( child => {
t.resolved.sharedProps.forEach( p => generatePropertyAccess(child, p, artifactConfig, fqn) )
})


node.indent( child => {
childRecords.forEach( r => {
Expand All @@ -59,31 +52,24 @@ export function generateUnion(t: MResolvedUnionType, artifactConfig: JavaServerJ
};
}

function generateUnionRecordContent(node: IndentNode, t: MResolvedRecordType, p: MResolvedUnionType, artifactConfig: JavaServerJakartaWSConfig, fqn: (type: string) => string) {
node.append(`public static class ${t.name}DTO extends ${p.name}DTO {`,NL)
function generateUnionRecordContent(node: IndentNode, t: MResolvedRecordType, p: MResolvedUnionType, artifactConfig: JavaServerJakartaWSGeneratorConfig, fqn: (type: string) => string) {
node.append(`public static class ${t.name}DTO extends ${p.name}DTO implements ${artifactConfig.rootPackageName}.service.dto.${p.name}DTO.${t.name}DTO {`,NL)

const sharedProps = t.resolved.unions.flatMap(u => u.resolved.sharedProps);

const allProps = allRecordProperties(t);
allProps
.filter(isMProperty)
.filter(p => p.variant === 'inline-enum')
.filter(p => !sharedProps.includes(p))
.forEach( p => {
const inlineEnum = p.type;
if( isMInlineEnumType(inlineEnum) ) {
generateInlineEnum(inlineEnum, toFirstUpper(p.name), node)
}
});


node.indent( child => {
allProps.filter(p => !sharedProps.includes(p)).forEach( p => generateProperty(child, p, artifactConfig, fqn))
})
node.indent( child => {
allProps.filter(p => !sharedProps.includes(p)).forEach( p => generatePropertyAccess(child, p, artifactConfig, fqn))
})

node.append('}',NL)
}

function generateProperty(node: IndentNode, property: MKeyProperty | MRevisionProperty | MProperty, artifactConfig: JavaServerJakartaWSConfig, fqn: (type: string) => string) {
function generateProperty(node: IndentNode, property: MKeyProperty | MRevisionProperty | MProperty, artifactConfig: JavaServerJakartaWSGeneratorConfig, fqn: (type: string) => string) {
if( isMKeyProperty(property) ) {
node.append(`public ${builtinToJavaType(property.type, fqn)} ${property.name};`,NL)
} else if( isMRevisionProperty(property) ) {
Expand All @@ -105,4 +91,57 @@ function generateProperty(node: IndentNode, property: MKeyProperty | MRevisionPr
node.append(`public ${toFirstUpper(property.name)} ${property.name};`,NL)
}
}
}

function generatePropertyAccess(node: IndentNode, property: MKeyProperty | MRevisionProperty | MProperty, artifactConfig: JavaServerJakartaWSGeneratorConfig, fqn: (type: string) => string) {
node.appendNewLine();
if( isMKeyProperty(property) ) {
node.append(`public ${builtinToJavaType(property.type, fqn)} ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}',NL);
} else if( isMRevisionProperty(property) ) {
node.append(`public ${builtinToJavaType(property.type, fqn)} ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL)
} else {
if( property.variant === 'union' || property.variant === 'record' ) {
if( property.array ) {
node.append(`public ${fqn('java.util.List')}<${property.type}DTO> ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL)
} else {
node.append(`public ${property.type}DTO ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL)
}
} else if( typeof property.type === 'string' ) {
if( property.array ) {
node.append(`public ${fqn('java.util.List')}<${resolveObjectType(property.type, artifactConfig.nativeTypeSubstitues, fqn)}> ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL)
} else {
node.append(`public ${resolveType(property.type, artifactConfig.nativeTypeSubstitues, fqn)} ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL)
}
} else {
node.append(`public ${toFirstUpper(property.name)} ${property.name}() {`,NL)
node.indent( body => {
body.append(`return this.${property.name};`,NL);
} )
node.append('}', NL);
}
}
}
15 changes: 15 additions & 0 deletions dsl/src/cli/java-server/base-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { toString } from "langium/generate";

import { Artifact } from "../artifact-generator.js";
import { generateCompilationUnit, JavaClientAPIGeneratorConfig, JavaImportsCollector, toPath } from "../java-gen-utils.js";
import { generateBaseDTOContent } from "../java-client-api/base-dto.js";

export function generateBaseDTO(artifactConfig: JavaClientAPIGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.service.dto`;

return {
name: 'BaseDTO.java',
content: toString(generateCompilationUnit(packageName, new JavaImportsCollector(packageName), generateBaseDTOContent())),
path: toPath(artifactConfig.targetFolder, packageName)
}
}
31 changes: 31 additions & 0 deletions dsl/src/cli/java-server/builder-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expandToString } from "langium/generate";

import { Artifact } from "../artifact-generator.js";
import { JavaClientAPIGeneratorConfig, toPath } from "../java-gen-utils.js";

export function generateDTOBuilderFactory(artifactConfig: JavaClientAPIGeneratorConfig): Artifact {
const packageName = `${artifactConfig.rootPackageName}.service`;

return {
name: 'DTOBuilderFactory.java',
content: generateDTOBuilderFactoryContent(packageName),
path: toPath(artifactConfig.targetFolder, packageName)
}
}

function generateDTOBuilderFactoryContent(packageName: string) {
const content = expandToString`
// Generated by RSD - Do not modify
package ${packageName};
import ${packageName}.dto.BaseDTO;
public interface DTOBuilderFactory {
public interface Builder {
public BaseDTO build();
}
public <T extends BaseDTO.Builder> T builder(Class<T> type);
}`
return content;
}
Empty file added dsl/src/cli/java-server/enum.ts
Empty file.
Loading

0 comments on commit a5c7f1f

Please sign in to comment.