UNPKG

@sap-cloud-sdk/util

Version:

SAP Cloud SDK for JavaScript general utilities

131 lines • 7.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UniqueNameGenerator = void 0; /** * Holds state on already used names and provides new names if there are naming conflicts. */ class UniqueNameGenerator { static getNameForComparison(name, caseSensitive) { return caseSensitive ? name : name.toLowerCase(); } /** * Creates an instance of UniqueNameGenerator. * @param indexSeparator - The separator to be used when adding an index. * @param usedNames - Sets the already used names considered in the finding process. */ constructor(indexSeparator = '_', usedNames = []) { this.indexSeparator = indexSeparator; this.usedNames = []; this.addToUsedNames(...usedNames); } /** * Adds the name(s) to the already used names. * @param names - Names to be added. */ addToUsedNames(...names) { this.usedNames.push(...names); } /** * Generate a unique name by appending an index separated by the `indexSeparator` if necessary, e.g. if `MyName` is already taken `MyName_1` will be found by default. * If the name is already unique nothing is appended. * @param name - The name to get a unique name from. * @param caseSensitive - Whether to check the already used names in a case sensitive manner. * @returns A unique name. */ generateUniqueName(name, caseSensitive = true) { return this.generateUniqueNamesWithSuffixes(name, [], caseSensitive)[0]; } /** * Generate a unique name by appending an index separated by the `indexSeparator` if necessary, e.g. if `MyName` is already taken `MyName_1` will be found by default. * The generated name is added to the used names. * If the name is already unique nothing is appended. * @param name - The name to get a unique name from. * @param caseSensitive - Whether to check the already used names in a case sensitive manner. * @returns A unique name. */ generateAndSaveUniqueName(name, caseSensitive = true) { const uniqueName = this.generateUniqueName(name, caseSensitive); this.addToUsedNames(uniqueName); return uniqueName; } /** * Generate unique names by appending an index separated by the `indexSeparator` if necessary, while respecting the given suffixes. * If the name is already unique nothing is appended. * Each given suffix is appended to the unique name in the result. * The resulting names are also checked for uniqueness. * All names in the result have the same number suffix. * @example if `MyName` and `MyName_1MySuffix` is already taken, `[MyName_2, MyName_2MySuffix]` will be generated by default. * @param name - The name to get a unique name from. * @param suffixes - Additional name of suffixes to be considered for the finding process, as well as the output. * @param caseSensitive - Whether to check the already used names in a case sensitive manner. * @returns A list of unique names. The length of this array is one plus the number of suffixes provided. The first entry corresponds to the given name. */ generateUniqueNamesWithSuffixes(name, suffixes, caseSensitive = true) { // Filter names to those that might be relevant for performance reasons const relevantUsedNames = this.getUsedNamesStartingWith(name, caseSensitive); const namesWithSuffixes = this.generateNamesWithSuffixes(name, suffixes); // Names do not need index if (!this.areNamesUsed(namesWithSuffixes, relevantUsedNames, caseSensitive)) { return [name, ...namesWithSuffixes]; } // Names do need index const index = this.getUniqueIndex(name, relevantUsedNames, suffixes, caseSensitive); return this.generateNamesWithIndexAndSuffixes(name, index, suffixes); } /** * Generate unique names by appending an index separated by the `indexSeparator` if necessary, while respecting the given suffixes. * If the name is already unique nothing is appended. * The generated names are added to the used names. * Each given suffix is appended to the unique name in the result. * The resulting names are also checked for uniqueness. * All names in the result have the same number suffix. * @example if `MyName` and `MyName_1MySuffix` is already taken, `[MyName_2, MyName_2MySuffix]` will be generated by default. * @param name - The name to get a unique name from. * @param suffixes - Additional name of suffixes to be considered for the finding process, as well as the output. * @param caseSensitive - Whether to check the already used names in a case sensitive manner. * @returns A list of unique names. The length of this array is one plus the number of suffixes provided. The first entry corresponds to the given name. */ generateAndSaveUniqueNamesWithSuffixes(name, suffixes, caseSensitive = true) { const uniqueNames = this.generateUniqueNamesWithSuffixes(name, suffixes, caseSensitive); this.addToUsedNames(...uniqueNames); return uniqueNames; } getUsedNamesForComparison(caseSensitive) { return this.usedNames.map(name => UniqueNameGenerator.getNameForComparison(name, caseSensitive)); } areNamesUsed(names, usedNames, caseSensitive) { return names.some(name => usedNames .map(usedName => UniqueNameGenerator.getNameForComparison(usedName, caseSensitive)) .includes(UniqueNameGenerator.getNameForComparison(name, caseSensitive))); } generateNamesWithIndexAndSuffixes(name, index, suffixes) { const nameWithoutIndex = this.getNameWithoutIndex(name); return this.generateNamesWithSuffixes(`${nameWithoutIndex}${this.indexSeparator}${index}`, suffixes); } generateNamesWithSuffixes(name, suffixes) { return [name, ...suffixes.map(nameSuffix => `${name}${nameSuffix}`)]; } getUsedNamesStartingWith(name, caseSensitive) { const modifiedName = this.getNameWithoutIndex(name); return this.getUsedNamesForComparison(caseSensitive).filter(used => used.startsWith(UniqueNameGenerator.getNameForComparison(modifiedName, caseSensitive))); } getUniqueIndex(name, usedNames, suffixes, caseSensitive) { let index = 1; // This algorithm has order N**2 for N identical names. With a sort you could get it down to N*log(N). // However with the related items in mind this is much easier and N should be small anyway. while (index < UniqueNameGenerator.MAXIMUM_NUMBER_OF_SUFFIX) { const newNames = this.generateNamesWithIndexAndSuffixes(name, index, suffixes); if (!this.areNamesUsed(newNames, usedNames, caseSensitive)) { return index; } index++; } throw new Error(`Unable to find a unique name for ${name} within the range of ${UniqueNameGenerator.MAXIMUM_NUMBER_OF_SUFFIX} suffixes.`); } getNameWithoutIndex(name) { return name.replace(new RegExp(`${this.indexSeparator}\\d+$`), ''); } } exports.UniqueNameGenerator = UniqueNameGenerator; UniqueNameGenerator.MAXIMUM_NUMBER_OF_SUFFIX = 1000; //# sourceMappingURL=unique-name-generator.js.map