import { Rule } from '@angular-devkit/schematics'; import { camelize, classify } from '@angular-devkit/core/src/utils/strings'; import { ModelField, Model } from '@vmfvmf/ywtc-lib'; import { BackEndGenerator } from '../../../shared/generator'; import { getPrjSrd } from '../../../router.gen'; import { ClassRelationEnum, UcType } from '@vmfvmf/ywtc-lib/dist/model.enums'; let importsSet: Set; let repositoriesSet: Set; let usesSet: Set; export function gen(model: Model): Rule { importsSet = new Set(); repositoriesSet = new Set(); usesSet = new Set(); let mappingsStr = ''; let usesStr = ''; let imports = ''; mappingsStr = [getToEntityStr(model), getEnumCollectionStr(model.fields)].join('\n\n'); usesStr = usesSet.size > 0 ? `, uses = {${Array.from(usesSet).join(', ')}}` : ''; imports = Array.from(importsSet).sort().join('\n'); mappingsStr = Array.from(repositoriesSet).join('\n\n') + '\n\n' + mappingsStr; return new BackEndGenerator(__filename).gen( {...model, ...getPrjSrd(), mappingsStr, imports, usesStr }); } function getToEntityStr(model: Model) { let result = ''; let toEntitySet = new Set(); let toFilterSet = new Set(); let patchWithDtoSet = new Set(); let toDtoSet = new Set(); model.relations.forEach(rel => { const relOtherName = camelize(rel.toModelName); const relVarName = camelize(rel.name); const relPackName = relOtherName.toLowerCase(); const relMethodName = classify(rel.name); importsSet.add('import org.mapstruct.Mapping;'); toFilterSet.add(`@Mapping(target = "${relVarName}", ignore = true)`); switch(rel.relation) { case ClassRelationEnum.OneToOne: importsSet.add(`${getPrjSrd().prjImpBse}.backend.${relPackName}.${rel.toModelName}Mapper;`); usesSet.add(`${rel.toModelName}Mapper.class`); break; case ClassRelationEnum.OneToMany: addRepositoryMapper(rel.toModelName, relPackName, 'Mapper'); importsSet.add('import org.mapstruct.MappingTarget;'); break; case ClassRelationEnum.ManyToOne: addRepositoryMapper(rel.toModelName, relPackName, 'Repository'); importsSet.add(`${getPrjSrd().prjImpBse}.backend.${relPackName}.${rel.toModelName}Mapper;`); usesSet.add(`${rel.toModelName}Mapper.class`); toDtoSet.add(`@Mapping(target = "${relVarName}Id", source = "${relVarName}.id")`); toEntitySet.add(`@Mapping(target = "${relVarName}", expression = "java(getFromRepository(dto.${relVarName}Id(), ${relOtherName}Repository))")`); break; case ClassRelationEnum.ManyToMany: importsSet.add('import org.mapstruct.MappingTarget;'); addRepositoryMapper(rel.toModelName, relPackName); toEntitySet.add(`@Mapping(target = "${relVarName}", expression = "java(toEntity(dto.${relVarName}Ids(), ${relOtherName}Repository))")`); patchWithDtoSet.add(`@Mapping(target = "${relVarName}", expression = "java(patchChildIdList(enty.get${relMethodName}(), dto.${relVarName}Ids(), ${relOtherName}Repository))")`); toDtoSet.add(`@Mapping(target = "${relVarName}Ids", expression = "java(toIdList(enty.get${relMethodName}()))")`) ; break; } }); if (toDtoSet.size > 0) { result += ['@Override', ...toDtoSet, `public abstract ${model.name}Dto toDto(${model.name} enty);`] .map(s => `\t${s}`).join('\n') + '\n\n'; } if (toFilterSet.size > 0) { importsSet.add('import org.mapstruct.Named;'); result += ['@Override', '@Named("toFilter")',...toFilterSet, `public abstract ${model.name} toFilter(${model.name}Dto dto);`] .map(s => `\t${s}`).join('\n') + '\n\n'; } if (toEntitySet.size > 0) { result += ['@Override', ...toEntitySet, `public abstract ${model.name} toEntity(${model.name}Dto dto);`] .map(s => `\t${s}`).join('\n') + '\n\n'; } if (patchWithDtoSet.size > 0) { result += ['@Override', ...patchWithDtoSet, `public abstract void patchWithDto(${model.name}Dto dto, @MappingTarget ${model.name} enty);`] .map(s => `\t${s}`).join('\n') + '\n\n'; } return result; } function addRepositoryMapper(toModelClass: string, modelPackName: string, repoMapper: 'Repository'|'Mapper' = 'Repository') { importsSet.add(`import org.springframework.beans.factory.annotation.Autowired;`); importsSet.add(`${getPrjSrd().prjImpBse}.backend.${modelPackName}.${toModelClass + repoMapper};`); repositoriesSet.add(`\t@Autowired\n\tprotected ${toModelClass + repoMapper} ${camelize(modelPackName) + repoMapper};`); if (repoMapper == 'Mapper') { usesSet.add(`${toModelClass + repoMapper}.class`); } } function getEnumCollectionStr(fields: ModelField[]) { return fields .filter(f => f.enumDefId != null && f.collection != null) .map(f => { const enumName = f.enumDefName; const enumNameVar = camelize(enumName); importsSet.add(`import java.util.stream.Stream;`); importsSet.add(`import java.util.List;`); importsSet.add(`import ${getPrjSrd().grpArtfId}.backend.enums.${enumName};`); return `\tprotected List<${enumName}> to${enumName}List(String ${enumNameVar}) { if (${enumNameVar} != null) return Stream.of(${enumNameVar}.split(",")).map(eStr -> ${enumName}.valueOf(eStr)).toList(); return null; } protected String to${enumName}String(List<${enumName}> ${enumNameVar}) { if (${enumNameVar} != null && !${enumNameVar}.isEmpty()) return String.join(",", ${enumNameVar}.stream().map(eDef -> eDef.name()).toList()); return null; } `; }) .join('\n\n'); }