UNPKG

@finos/legend-extension-dsl-data-quality

Version:
189 lines (153 loc) 5.31 kB
/** * Copyright (c) 2026-present, Goldman Sachs * * 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 { CollectionInstanceValue, PrimitiveInstanceValue, } from '@finos/legend-graph'; import { DataQualityFunctionDefaults } from './DataQualityFunctionDefaults.js'; import { DataQualityValidationPropertyGuarantee, type DataQualityValidationAssertionFunction, type DataQualityValidationCustomHelperFunction, type DataQualityValidationFilterCondition, type DataQualityValidationFilterFunction, type DataQualityValidationFunctionVisitor, type DataQualityValidationLogicalGroupFunction, } from './DataQualityValidationFunction.js'; import { hashArray } from '@finos/legend-shared'; export class DataQualityValidationNameGeneratorVisitor implements DataQualityValidationFunctionVisitor<string> { depth = 0; visitAssertion(func: DataQualityValidationAssertionFunction): string { return ''; } visitCustomHelper(func: DataQualityValidationCustomHelperFunction): string { const { column, otherParams } = func.parameters; const values: string[] = []; const nameTemplate = DataQualityFunctionDefaults.getFunctionNameTemplate( func.name, ); const columnName = column.values[0]?.name; if (!columnName || !nameTemplate) { return ''; } otherParams.forEach((param) => { if (param instanceof PrimitiveInstanceValue) { const value = param.values[0] as string; values.push(String(value)); } if (param instanceof CollectionInstanceValue) { values.push('List'); } }); return this.composeName(columnName, values, nameTemplate); } visitFilter(func: DataQualityValidationFilterFunction): string { const { lambda } = func.parameters; return this.splitAndHashLongNames(lambda.body.accept(this), 3); } visitFilterCondition(func: DataQualityValidationFilterCondition): string { const { property, otherParams } = func.parameters; const values: string[] = []; const nameTemplate = DataQualityFunctionDefaults.getFunctionNameTemplate( func.name, ); let columnName = ''; if (property instanceof DataQualityValidationPropertyGuarantee) { columnName = property.parameters.property.func.value.name; } else { columnName = property.func.value.name; } if (!columnName || !nameTemplate) { return ''; } otherParams.forEach((param) => { if (param instanceof PrimitiveInstanceValue) { const value = param.values[0] as string; values.push(String(value)); } if (param instanceof CollectionInstanceValue) { values.push('_List'); } }); return this.composeName(columnName, values, nameTemplate); } visitLogicalGroup(func: DataQualityValidationLogicalGroupFunction): string { const leftName = this.capitalizeFirstLetter( func.parameters.left.accept(this), ); const rightName = this.capitalizeFirstLetter( func.parameters.right.accept(this), ); const operator = this.capitalizeFirstLetter(func.name); if (!leftName && !rightName) { return ''; } return `${leftName}${operator}${rightName}`; } visitPropertyGuarantee(): string { return ''; } private composeName( columnName: string, params: string[], nameTemplate: string, ): string { let name = nameTemplate; name = name.replace(/\[column\]/gi, this.toCamelCase(columnName)); params.forEach((param, index) => { const placeholder = new RegExp(`\\[param-${index + 1}\\]`, 'giu'); name = name.replace( placeholder, this.capitalizeFirstLetter(param.trim()), ); }); return name; } private splitAndHashLongNames(str: string, maxParts: number = 4): string { const parts = str.split(/(?=And|Or)/g).filter((part) => part.length > 0); if (parts.length <= maxParts) { return str; } const keepParts = parts.slice(0, maxParts - 1); const remainingParts = parts.slice(maxParts - 1); const hash = hashArray(remainingParts).slice(0, 6); return `${keepParts.join('')}_${hash}`; } private capitalizeFirstLetter(str: string) { return str.charAt(0).toUpperCase() + str.slice(1); } private toCamelCase(str: string): string { if (!str) { return ''; } // Split by common delimiters: spaces, underscores, hyphens, dots const words = str.split(/[\s_\-\.]+/g).filter((word) => word.length > 0); if (words.length === 0) { return ''; } return words .map((word, index) => { const lowerWord = word.toLowerCase(); if (index === 0) { return lowerWord; } return lowerWord.charAt(0).toUpperCase() + lowerWord.slice(1); }) .join(''); } }