import { createLogger , last } from '@sap-cloud-sdk/util' ; import { edmToFieldType , edmToTsType , getFallbackEdmTypeIfNeeded , isCreatable , isDeletable , isNullableProperty , isUpdatable } from '../../generator-utils' ; import { VdmComplexType , VdmEntity , VdmNavigationProperty , VdmProperty , VdmMappedEdmType , VdmEnumType } from '../../vdm-types' ; import { ServiceNameFormatter } from '../../service-name-formatter' ; import { applyPrefixOnJsConflictParam } from '../../name-formatting-strategies' ; import { entityDescription , propertyDescription } from '../description-util' ; import { EdmxEntitySetBase , EdmxEntityTypeBase , EdmxNamed , JoinedEntityMetadata } from '../../edmx-parser/common' ; import { checkCollectionKind , complexTypeFieldType , isCollectionType , isComplexType , isEdmType , isEnumType , parseCollectionTypeName , typesForCollection } from '../edmx-to-vdm-util' ; import { SwaggerMetadata } from '../../swagger-parser/swagger-types' ; const logger = createLogger ( { package : 'generator' , messageContext : 'entity' } ) ; internal export function transformEntityBase ( entityMetadata , classNames , complexTypes , enumTypes , formatter ) { const entity = { entitySetName : entityMetadata . entitySet . Name , entityTypeName : entityMetadata . entityType . Name , entityTypeNamespace : entityMetadata . entityType . Namespace , className : classNames [ entityMetadata . entitySet . Name ] , properties : properties ( entityMetadata , complexTypes , formatter , enumTypes ) , creatable : entityMetadata . entitySet ? isCreatable ( entityMetadata . entitySet ) : true , updatable : entityMetadata . entitySet ? isUpdatable ( entityMetadata . entitySet ) : true , deletable : entityMetadata . entitySet ? isDeletable ( entityMetadata . entitySet ) : true } ; return { ... entity , keys : keys ( entity . properties , entityMetadata . entityType . Key . PropertyRef ) , description : entityDescription ( entityMetadata , entity . className ) } ; } function keys ( props , edmxKeys ) { return edmxKeys . map ( key => props . find ( prop => prop . originalName === key . Name ) ) . filter ( e => ! ! e ) as VdmProperty [ ] ; } function properties ( entity , complexTypes , formatter , enumTypes ) { return entity . entityType . Property . map ( p => { checkCollectionKind ( p ) ; const swaggerProp = entity . swaggerDefinition ? entity . swaggerDefinition . properties [ p . Name ] : undefined ; const instancePropertyName = formatter . originalToInstancePropertyName ( entity . entitySet . Name , p . Name ) ; const isCollection = isCollectionType ( p . Type ) ; const parsed = isCollection ? parseCollectionTypeName ( p . Type ) : p . Type ; const isComplex = isComplexType ( parsed , complexTypes ) ; const isEnum = isEnumType ( parsed , enumTypes ) ; const typeMapping = getTypeMappingEntityProperties ( p . Type , complexTypes , enumTypes , isComplex , isEnum ) ; return { originalName : p . Name , instancePropertyName , staticPropertyName : formatter . originalToStaticPropertyName ( entity . entitySet . Name , p . Name ) , propertyNameAsParam : applyPrefixOnJsConflictParam ( instancePropertyName ) , edmType : typeMapping . edmType , jsType : typeMapping . jsType , fieldType : typeMapping . fieldType , description : propertyDescription ( p , swaggerProp ) , nullable : isNullableProperty ( p ) , maxLength : p . MaxLength , isComplex , isEnum , isCollection } ; } ) ; } internal export function joinEntityMetadata < EntitySetT extends EdmxEntitySetBase , EntityTypeT extends EdmxEntityTypeBase < any > > ( entitySets , entityTypes , swagger ? ) { return entitySets . map ( entitySet => { let entityType = entityTypes . find ( t => `${ t . Namespace }.${ t . Name }` === entitySet . EntityType ) ; if ( ! entityType ) { entityType = entityTypes . find ( t => t . Name === last ( entitySet . EntityType . split ( '.' ) ) ) ; } if ( ! entityType ) { throw Error ( `Could not find entity type '${ entitySet . EntityType }' for entity set with name '${ entitySet . Name }'.'` ) ; } const joined = { entitySet , entityType } ; if ( swagger ) { const defKey = Object . keys ( swagger . definitions ) . find ( name => `${ entityType ! . Namespace }.${ name }` === entitySet . EntityType ) ; if ( defKey ) { joined . swaggerDefinition = swagger . definitions [ defKey ] ; } } return joined ; } ) ; } internal export function navigationPropertyBase ( navPropName , entitySetName , formatter ) { const instancePropertyName = formatter . originalToNavigationPropertyName ( entitySetName , navPropName ) ; return { originalName : navPropName , instancePropertyName , staticPropertyName : formatter . originalToStaticPropertyName ( entitySetName , navPropName ) , propertyNameAsParam : applyPrefixOnJsConflictParam ( instancePropertyName ) } ; } internal export function createEntityClassNames ( entityMetadata , formatter ) { return entityMetadata . reduce ( ( names , e ) => ( { ... names , [ e . entitySet . Name ] : formatter . originalToEntityClassName ( e . entitySet . Name ) } ) , { } ) ; } function getTypeMappingEntityProperties ( typeName , complexTypes , enumTypes , isComplex , isEnum ) { if ( isEdmType ( typeName ) ) { const edmFallback = getFallbackEdmTypeIfNeeded ( typeName ) ; return { edmType : edmFallback , jsType : edmToTsType ( edmFallback ) , fieldType : edmToFieldType ( edmFallback ) } ; } if ( isCollectionType ( typeName ) ) { return typesForCollection ( typeName , enumTypes , complexTypes ) ; } if ( isComplex ) { return { edmType : typeName , jsType : complexTypeForName ( typeName , complexTypes ) , fieldType : complexTypeFieldForName ( typeName , complexTypes ) } ; } if ( isEnum ) { return { edmType : typeName , jsType : enumTypeForName ( typeName , enumTypes ) , fieldType : 'EnumField' } ; } throw new Error ( `No types found for ${ typeName }` ) ; } function complexTypeFieldForName ( name , complexTypes ) { const complexType = findComplexType ( name , complexTypes ) ; if ( complexType ) { return complexTypeFieldType ( complexType . typeName ) ; } logger . warn ( `No complex type mapping found for ${ name }! Using "any" instead. This will most likely result in errors.` ) ; return 'any' ; } const getPostfix = ( type ) => last ( type . split ( '.' ) ) ; internal export const findComplexType = ( name , complexTypes ) : Omit < VdmComplexType , 'factoryName' > | undefined => complexTypes . find ( c => c . originalName === getPostfix ( name ) ) ; internal export const findEnumType = ( name , enumTypes ) : VdmEnumType | undefined => enumTypes . find ( e => e . originalName === getPostfix ( name ) ) ; internal export function complexTypeForName ( name , complexTypes ) { const complexType = findComplexType ( name , complexTypes ) ; if ( complexType ) { return complexType . typeName ; } logger . warn ( `No complex type mapping found for ${ name }! Using "any" instead. This will most likely result in errors.` ) ; return 'any' ; } internal export function enumTypeForName ( name , enumTypes ) { const enumType = findEnumType ( name , enumTypes ) ; if ( enumType ) { return enumType . typeName ; } logger . warn ( `No enum type mapping found for ${ name }! Using "any" instead. This will most likely result in errors.` ) ; return 'any' ; }