@finos/legend-graph
Version:
Legend graph and graph manager
745 lines • 35.1 kB
JavaScript
/**
* Copyright (c) 2020-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 { UnsupportedOperationError, getClass, IllegalStateError, returnUndefOnError, promisify, filterByType, guaranteeNonNullable, guaranteeType, isNonNullable, isType, } from '@finos/legend-shared';
import { Package } from '../graph/metamodel/pure/packageableElements/domain/Package.js';
import { Type } from '../graph/metamodel/pure/packageableElements/domain/Type.js';
import { Association } from '../graph/metamodel/pure/packageableElements/domain/Association.js';
import { Mapping } from '../graph/metamodel/pure/packageableElements/mapping/Mapping.js';
import { Class } from '../graph/metamodel/pure/packageableElements/domain/Class.js';
import { Enumeration } from '../graph/metamodel/pure/packageableElements/domain/Enumeration.js';
import { PackageableElement } from '../graph/metamodel/pure/packageableElements/PackageableElement.js';
import { Profile } from '../graph/metamodel/pure/packageableElements/domain/Profile.js';
import { Service } from '../graph/metamodel/pure/packageableElements/service/Service.js';
import { ConcreteFunctionDefinition } from './metamodel/pure/packageableElements/function/ConcreteFunctionDefinition.js';
import { Store } from '../graph/metamodel/pure/packageableElements/store/Store.js';
import { FlatData } from '../graph/metamodel/pure/packageableElements/store/flatData/model/FlatData.js';
import { PackageableRuntime } from '../graph/metamodel/pure/packageableElements/runtime/PackageableRuntime.js';
import { PackageableConnection } from '../graph/metamodel/pure/packageableElements/connection/PackageableConnection.js';
import { FileGenerationSpecification } from '../graph/metamodel/pure/packageableElements/fileGeneration/FileGenerationSpecification.js';
import { GenerationSpecification } from '../graph/metamodel/pure/packageableElements/generationSpecification/GenerationSpecification.js';
import { Unit, Measure, } from '../graph/metamodel/pure/packageableElements/domain/Measure.js';
import { Database } from '../graph/metamodel/pure/packageableElements/store/relational/model/Database.js';
import { SectionIndex } from '../graph/metamodel/pure/packageableElements/section/SectionIndex.js';
import { PureGraphExtension } from './PureGraphExtension.js';
import { PrimitiveType } from '../graph/metamodel/pure/packageableElements/domain/PrimitiveType.js';
import { DataType } from '../graph/metamodel/pure/packageableElements/domain/DataType.js';
import { isValidFullPath, isValidPath, resolvePackagePathAndElementName, } from '../graph/MetaModelUtils.js';
import { addElementToPackage, deleteElementFromPackage, getFunctionName, getOrCreateGraphPackage, getOrCreatePackage, } from '../graph/helpers/DomainHelper.js';
import { DataElement } from '../graph/metamodel/pure/packageableElements/data/DataElement.js';
import { ExecutionEnvironmentInstance } from './metamodel/pure/packageableElements/service/ExecutionEnvironmentInstance.js';
import { INTERNAL__UnknownPackageableElement } from './metamodel/pure/packageableElements/INTERNAL__UnknownPackageableElement.js';
import { FunctionActivator } from './metamodel/pure/packageableElements/function/FunctionActivator.js';
import { INTERNAL__UnknownFunctionActivator } from './metamodel/pure/packageableElements/function/INTERNAL__UnknownFunctionActivator.js';
import { INTERNAL__UnknownStore } from './metamodel/pure/packageableElements/store/INTERNAL__UnknownStore.js';
import { INTERNAL__UnknownElement } from './metamodel/pure/packageableElements/INTERNAL__UnknownElement.js';
import { DataProduct } from './metamodel/pure/dataProduct/DataProduct.js';
import { IngestDefinition } from './metamodel/pure/packageableElements/ingest/IngestDefinition.js';
const FORBIDDEN_EXTENSION_ELEMENT_CLASS = new Set([
PackageableElement,
Type,
DataType,
PrimitiveType,
Class,
Association,
Enumeration,
ConcreteFunctionDefinition,
Profile,
Measure,
Unit,
DataElement,
Store,
Mapping,
PackageableConnection,
PackageableRuntime,
GenerationSpecification,
FileGenerationSpecification,
Service, // to be modularized
ExecutionEnvironmentInstance,
SectionIndex,
INTERNAL__UnknownPackageableElement,
INTERNAL__UnknownStore,
]);
/**
* Since this is the basis of the Pure graph itself, it shares many methods with the graph.
* But the graph holds references to many basic graphs and expose those to outside consumers
* as if it is one graph.
*
* As such, to avoid confusion, we add `Own` to methods in basic graph for methods that only
* deal with elements belonging to the basic graph.
*/
export class BasicModel {
root;
_origin;
extensions = [];
graphPlugins = [];
elementSectionIndex = new Map();
sectionIndicesIndex = new Map();
profilesIndex = new Map();
typesIndex = new Map();
associationsIndex = new Map();
functionsIndex = new Map();
functionActivatorsIndex = new Map();
storesIndex = new Map();
mappingsIndex = new Map();
connectionsIndex = new Map();
runtimesIndex = new Map();
servicesIndex = new Map();
generationSpecificationsIndex = new Map();
fileGenerationsIndex = new Map();
productsIndex = new Map();
dataElementsIndex = new Map();
executionEnvironmentsIndex = new Map();
INTERNAL__unknownElementsIndex = new Map();
INTERNAL__unknownIndex = new Map();
constructor(rootPackageName, graphPlugins, origin) {
this.root = new Package(rootPackageName);
const extensionElementClasses = graphPlugins.flatMap((plugin) => plugin.getExtraPureGraphExtensionClasses?.() ?? []);
this.extensions = this.createGraphExtensions(extensionElementClasses);
this._origin = origin;
}
createGraphExtensions(extensionElementClasses) {
return extensionElementClasses.map((extensionElementClass) => {
if (FORBIDDEN_EXTENSION_ELEMENT_CLASS.has(extensionElementClass)) {
throw new IllegalStateError(`Pure graph extension not allowed for the specified class. Consider removing this extension from plugins.`);
}
return new PureGraphExtension(extensionElementClass);
});
}
get ownSectionIndices() {
return Array.from(this.sectionIndicesIndex.values());
}
get ownProfiles() {
return Array.from(this.profilesIndex.values());
}
get ownEnumerations() {
return Array.from(this.typesIndex.values()).filter(filterByType(Enumeration));
}
get ownMeasures() {
return Array.from(this.typesIndex.values()).filter(filterByType(Measure));
}
get ownClasses() {
return Array.from(this.typesIndex.values()).filter(filterByType(Class));
}
get ownTypes() {
return Array.from(this.typesIndex.values());
}
get ownAssociations() {
return Array.from(this.associationsIndex.values());
}
get ownFunctions() {
return Array.from(this.functionsIndex.values());
}
get ownFunctionActivators() {
return Array.from(this.functionActivatorsIndex.values());
}
get ownStores() {
return Array.from(this.storesIndex.values());
}
get ownFlatDatas() {
return Array.from(this.storesIndex.values()).filter(filterByType(FlatData));
}
get ownDatabases() {
return Array.from(this.storesIndex.values()).filter(filterByType(Database));
}
get ownMappings() {
return Array.from(this.mappingsIndex.values());
}
get ownServices() {
return Array.from(this.servicesIndex.values());
}
get ownRuntimes() {
return Array.from(this.runtimesIndex.values());
}
get ownConnections() {
return Array.from(this.connectionsIndex.values());
}
get ownFileGenerations() {
return Array.from(this.fileGenerationsIndex.values());
}
get ownProducts() {
return Array.from(this.productsIndex.values());
}
get ownDataElements() {
return Array.from(this.dataElementsIndex.values());
}
get ownExecutionEnvironments() {
return Array.from(this.executionEnvironmentsIndex.values());
}
get ownIngests() {
return Array.from(this.INTERNAL__unknownElementsIndex.values()).filter(filterByType(IngestDefinition));
}
get ownGenerationSpecifications() {
return Array.from(this.generationSpecificationsIndex.values());
}
get ownTestables() {
const coreTestables = [
...this.ownServices,
...this.ownMappings,
// TODO: re-add functions once function test runner has been completed in backend
// ...this.ownFunctions,
];
const filters = this.graphPlugins.flatMap((plugin) => plugin.getExtraTestablesCollectors?.() ?? []);
const extraTestables = this.allOwnElements
.map((element) => filters.find((elementFilter) => Boolean(elementFilter(element)))?.(element))
.filter(isNonNullable);
return [...coreTestables, ...extraTestables];
}
get origin() {
return this._origin;
}
setOrigin(val) {
if (this._origin) {
throw new IllegalStateError(`Graph origin has already been set`);
}
else {
this._origin = val;
}
}
getExtensionElements(extensionElementClass) {
return this.getExtensionForElementClass(extensionElementClass).elements;
}
getExtensionForElementClass(_class) {
const extensions = this.extensions.filter((extension) => extension.getElementClass() === _class);
if (extensions.length === 0) {
throw new UnsupportedOperationError(`Can't find graph extension for the specified element class: no compatible graph extensions available from plugins`);
}
else if (extensions.length > 1) {
throw new IllegalStateError(`Found multiple extensions for the specified element class`);
}
return extensions[0];
}
getOwnNullableSection = (path) => this.elementSectionIndex.get(path);
getOwnNullableSectionIndex = (path) => this.sectionIndicesIndex.get(path);
getOwnNullableProfile = (path) => this.profilesIndex.get(path);
getOwnNullableType = (path) => this.typesIndex.get(path);
getOwnNullableClass = (path) => {
const el = this.getOwnNullableType(path);
return el instanceof Class ? el : undefined;
};
getOwnNullableEnumeration = (path) => {
const el = this.getOwnNullableType(path);
return el instanceof Enumeration ? el : undefined;
};
getOwnNullableMeasure = (path) => {
const el = this.getOwnNullableType(path);
return el instanceof Measure ? el : undefined;
};
getOwnNullableAssociation = (path) => this.associationsIndex.get(path);
getOwnNullableFunction = (path) => this.functionsIndex.get(path);
getOwnNullableFunctionActivator = (path) => this.functionActivatorsIndex.get(path);
getOwnNullableStore = (path) => this.storesIndex.get(path);
getOwnNullableMapping = (path) => this.mappingsIndex.get(path);
getOwnNullableConnection = (path) => this.connectionsIndex.get(path);
getOwnNullableRuntime = (path) => this.runtimesIndex.get(path);
getOwnNullableService = (path) => this.servicesIndex.get(path);
getOwnNullableGenerationSpecification = (path) => this.generationSpecificationsIndex.get(path);
getOwnNullableFileGeneration = (path) => this.fileGenerationsIndex.get(path);
getOwnNullableDataElement = (path) => this.dataElementsIndex.get(path);
getOwnNullableExecutionEnviornment = (path) => this.executionEnvironmentsIndex.get(path);
getOwnNullableProduct = (path) => this.productsIndex.get(path);
getOwnSectionIndex = (path) => guaranteeNonNullable(this.getOwnNullableSectionIndex(path), `Can't find section index '${path}'`);
getOwnProfile = (path) => guaranteeNonNullable(this.getOwnNullableProfile(path), `Can't find profile '${path}'`);
getOwnType = (path) => guaranteeNonNullable(this.getOwnNullableType(path), `Can't find type '${path}'`);
getOwnClass = (path) => guaranteeNonNullable(this.getOwnNullableClass(path), `Can't find class '${path}'`);
getOwnEnumeration = (path) => guaranteeNonNullable(this.getOwnNullableEnumeration(path), `Can't find enumeration '${path}'`);
getOwnMeasure = (path) => guaranteeNonNullable(this.getOwnNullableMeasure(path), `Can't find measure '${path}'`);
getOwnAssociation = (path) => guaranteeNonNullable(this.getOwnNullableAssociation(path), `Can't find association '${path}'`);
getOwnFunction = (path) => guaranteeNonNullable(this.getOwnNullableFunction(path), `Can't find function '${path}'`);
getOwnFunctionActivator = (path) => guaranteeNonNullable(this.getOwnNullableFunctionActivator(path), `Can't find function activator '${path}'`);
getOwnStore = (path) => guaranteeNonNullable(this.getOwnNullableStore(path), `Can't find store '${path}'`);
getOwnDatabase = (path) => guaranteeType(this.getOwnNullableStore(path), Database, `Can't find database '${path}'`);
getOwnFlatDataStore = (path) => guaranteeType(this.getOwnNullableStore(path), FlatData, `Can't find flat-data store '${path}'`);
getOwnMapping = (path) => guaranteeNonNullable(this.getOwnNullableMapping(path), `Can't find mapping '${path}'`);
getOwnConnection = (path) => guaranteeNonNullable(this.getOwnNullableConnection(path), `Can't find connection '${path}'`);
getOwnRuntime = (path) => guaranteeNonNullable(this.getOwnNullableRuntime(path), `Can't find runtime '${path}'`);
getOwnService = (path) => guaranteeNonNullable(this.getOwnNullableService(path), `Can't find service '${path}'`);
getOwnGenerationSpecification = (path) => guaranteeNonNullable(this.getOwnNullableGenerationSpecification(path), `Can't find generation specification '${path}'`);
getOwnFileGeneration = (path) => guaranteeNonNullable(this.getOwnNullableFileGeneration(path), `Can't find file generation '${path}'`);
getOwnDataElement = (path) => guaranteeNonNullable(this.getOwnNullableDataElement(path), `Can't find data element '${path}'`);
getOwnExecutionEnvironment = (path) => guaranteeNonNullable(this.getOwnNullableExecutionEnviornment(path), `Can't find execution environment element '${path}'`);
getOwnDataProduct = (path) => guaranteeNonNullable(this.getOwnNullableProduct(path), `Can't find data product element '${path}'`);
getOwnNullableExtensionElement(path, extensionElementClass) {
const extension = this.getExtensionForElementClass(extensionElementClass);
return extension.getElement(path);
}
setOwnSection(path, val) {
this.elementSectionIndex.set(path, val);
}
setOwnSectionIndex(path, val) {
this.sectionIndicesIndex.set(path, val);
}
setOwnProfile(path, val) {
this.profilesIndex.set(path, val);
}
setOwnType(path, val) {
this.typesIndex.set(path, val);
}
setOwnAssociation(path, val) {
this.associationsIndex.set(path, val);
}
setOwnFunction(path, val) {
this.functionsIndex.set(path, val);
}
setOwnFunctionActivator(path, val) {
this.functionActivatorsIndex.set(path, val);
}
setOwnStore(path, val) {
this.storesIndex.set(path, val);
}
setOwnMapping(path, val) {
this.mappingsIndex.set(path, val);
}
setOwnConnection(path, val) {
this.connectionsIndex.set(path, val);
}
setOwnRuntime(path, val) {
this.runtimesIndex.set(path, val);
}
setOwnService(path, val) {
this.servicesIndex.set(path, val);
}
setOwnGenerationSpecification(path, val) {
this.generationSpecificationsIndex.set(path, val);
}
setOwnFileGeneration(path, val) {
this.fileGenerationsIndex.set(path, val);
}
setOwnDataElement(path, val) {
this.dataElementsIndex.set(path, val);
}
setOwnExecutionEnvironment(path, val) {
this.executionEnvironmentsIndex.set(path, val);
}
setOwnDataProduct(path, val) {
this.productsIndex.set(path, val);
}
INTERNAL__setOwnUnknown(path, val) {
this.INTERNAL__unknownIndex.set(path, val);
}
INTERNAL__setOwnUnknownElement(path, val) {
this.INTERNAL__unknownElementsIndex.set(path, val);
}
setOwnElementInExtension(path, val, extensionElementClass) {
const extension = this.getExtensionForElementClass(extensionElementClass);
extension.setElement(path, val);
}
get allOwnElements() {
return [
...this.ownProfiles,
...this.ownEnumerations,
...this.ownMeasures,
...this.ownClasses,
...this.ownAssociations,
...this.ownFunctions,
...this.ownFunctionActivators,
...this.ownStores,
...this.ownMappings,
...this.ownServices,
...this.ownRuntimes,
...this.ownConnections,
...this.ownGenerationSpecifications,
...this.ownFileGenerations,
...this.ownProducts,
...this.ownDataElements,
...this.ownExecutionEnvironments,
...Array.from(this.INTERNAL__unknownElementsIndex.values()),
...Array.from(this.INTERNAL__unknownIndex.values()),
...this.extensions.flatMap((extension) => extension.elements),
];
}
get knownAllOwnElements() {
return this.allOwnElements.filter((element) => !isType(element, INTERNAL__UnknownElement));
}
/**
* Dispose the current graph and any potential reference from parts outside of the graph to the graph
* This is a MUST to prevent memory-leak as we might have references between metamodels from this graph
* and other graphs
*/
async dispose() {
if (this.allOwnElements.length) {
await Promise.all(this.allOwnElements.map((element) => promisify(() => {
element.dispose();
})));
}
}
getNullablePackage = (path) => !path
? this.root
: returnUndefOnError(() => getOrCreatePackage(this.root, path, false, undefined));
getOwnNullableElement(path, includePackage) {
let element = this.sectionIndicesIndex.get(path) ??
this.INTERNAL__unknownIndex.get(path) ??
this.INTERNAL__unknownElementsIndex.get(path) ??
this.typesIndex.get(path) ??
this.profilesIndex.get(path) ??
this.associationsIndex.get(path) ??
this.functionsIndex.get(path) ??
this.functionActivatorsIndex.get(path) ??
this.storesIndex.get(path) ??
this.mappingsIndex.get(path) ??
this.servicesIndex.get(path) ??
this.runtimesIndex.get(path) ??
this.connectionsIndex.get(path) ??
this.fileGenerationsIndex.get(path) ??
this.productsIndex.get(path) ??
this.dataElementsIndex.get(path) ??
this.executionEnvironmentsIndex.get(path) ??
this.generationSpecificationsIndex.get(path);
if (!element) {
for (const extension of this.extensions) {
const extensionElement = extension.getElement(path);
if (extensionElement) {
element = extensionElement;
break;
}
}
}
if (includePackage && !element) {
return this.getNullablePackage(path);
}
return element;
}
addOwnElement(element, packagePath) {
addElementToPackage(packagePath
? getOrCreateGraphPackage(this, packagePath, undefined)
: this.root, element);
if (element instanceof Mapping) {
this.setOwnMapping(element.path, element);
}
else if (element instanceof Store) {
this.setOwnStore(element.path, element);
}
else if (element instanceof Type) {
this.setOwnType(element.path, element);
}
else if (element instanceof Association) {
this.setOwnAssociation(element.path, element);
}
else if (element instanceof Profile) {
this.setOwnProfile(element.path, element);
}
else if (element instanceof ConcreteFunctionDefinition) {
this.setOwnFunction(element.path, element);
}
else if (element instanceof FunctionActivator) {
this.setOwnFunctionActivator(element.path, element);
}
else if (element instanceof Service) {
this.setOwnService(element.path, element);
}
else if (element instanceof PackageableConnection) {
this.setOwnConnection(element.path, element);
}
else if (element instanceof PackageableRuntime) {
this.setOwnRuntime(element.path, element);
}
else if (element instanceof FileGenerationSpecification) {
this.setOwnFileGeneration(element.path, element);
}
else if (element instanceof GenerationSpecification) {
this.setOwnGenerationSpecification(element.path, element);
}
else if (element instanceof DataElement) {
this.setOwnDataElement(element.path, element);
}
else if (element instanceof ExecutionEnvironmentInstance) {
this.setOwnExecutionEnvironment(element.path, element);
}
else if (element instanceof DataProduct) {
this.setOwnDataProduct(element.path, element);
}
else if (element instanceof Package) {
// do nothing
}
else {
const extension = this.getExtensionForElementClass(getClass(element));
extension.setElement(element.path, element);
}
}
deleteOwnElement(element) {
if (element.package) {
deleteElementFromPackage(element.package, element);
}
if (element instanceof INTERNAL__UnknownElement) {
this.INTERNAL__unknownIndex.delete(element.path);
}
else if (element instanceof INTERNAL__UnknownPackageableElement) {
this.INTERNAL__unknownElementsIndex.delete(element.path);
}
else if (element instanceof Mapping) {
this.mappingsIndex.delete(element.path);
}
else if (element instanceof Store) {
this.storesIndex.delete(element.path);
}
else if (element instanceof Type) {
this.typesIndex.delete(element.path);
if (element instanceof Measure) {
if (element.canonicalUnit) {
this.typesIndex.delete(element.canonicalUnit.path);
}
element.nonCanonicalUnits.forEach((unit) => this.typesIndex.delete(unit.path));
}
}
else if (element instanceof Association) {
this.associationsIndex.delete(element.path);
}
else if (element instanceof Profile) {
this.profilesIndex.delete(element.path);
}
else if (element instanceof ConcreteFunctionDefinition) {
this.functionsIndex.delete(element.path);
}
else if (element instanceof FunctionActivator) {
this.functionActivatorsIndex.delete(element.path);
}
else if (element instanceof Service) {
this.servicesIndex.delete(element.path);
}
else if (element instanceof PackageableRuntime) {
this.runtimesIndex.delete(element.path);
}
else if (element instanceof PackageableConnection) {
this.connectionsIndex.delete(element.path);
}
else if (element instanceof FileGenerationSpecification) {
this.fileGenerationsIndex.delete(element.path);
}
else if (element instanceof GenerationSpecification) {
this.generationSpecificationsIndex.delete(element.path);
}
else if (element instanceof DataElement) {
this.dataElementsIndex.delete(element.path);
}
else if (element instanceof ExecutionEnvironmentInstance) {
this.executionEnvironmentsIndex.delete(element.path);
}
else if (element instanceof DataProduct) {
this.productsIndex.delete(element.path);
}
else if (element instanceof Package) {
element.children.forEach((child) => this.deleteOwnElement(child));
}
else {
const extension = this.getExtensionForElementClass(getClass(element));
extension.deleteElement(element.path);
}
}
/**
* NOTE: this method has to do with graph modification
* and as of the current set up, we should not allow it to be called
* on any immutable graphs. As such, we protect it and let the main graph
* expose it. The other benefit of exposing this in the main graph is that we could
* do better duplicated path check
*/
renameOwnElement(element, oldPath, newPath) {
// validation before renaming
if (oldPath === newPath) {
return;
}
if (!newPath) {
throw new UnsupportedOperationError(`Can't rename element '${oldPath} to '${newPath}': path is empty'`);
}
if ((element instanceof Package && !isValidPath(newPath)) ||
(!(element instanceof Package) && !isValidFullPath(newPath))) {
throw new UnsupportedOperationError(`Can't rename element '${oldPath} to '${newPath}': invalid path'`);
}
const existingElement = this.getOwnNullableElement(newPath, true);
if (existingElement) {
throw new UnsupportedOperationError(`Can't rename element '${oldPath} to '${newPath}': another element with the same path already existed'`);
}
const [newPackagePath, newElementName] = resolvePackagePathAndElementName(newPath);
// if we're not renaming package, we can simply add new package
// if the element new package does not exist. For renaming package
// it's a little bit more complicated as we need to rename its children
// we will handle this case later
if (!(element instanceof Package)) {
const newParentPackage = this.getNullablePackage(newPackagePath) ??
(newPackagePath !== ''
? getOrCreateGraphPackage(this, newPackagePath, undefined)
: this.root);
// update element name
element.name = newElementName;
if (element instanceof ConcreteFunctionDefinition) {
element.functionName = getFunctionName(element, element.name);
}
// update element package if needed
if (element.package !== newParentPackage) {
if (element.package) {
deleteElementFromPackage(element.package, element);
}
addElementToPackage(newParentPackage, element);
}
}
// update index in the graph
if (element instanceof INTERNAL__UnknownElement) {
this.INTERNAL__unknownIndex.delete(oldPath);
this.INTERNAL__unknownIndex.set(newPath, element);
element.content = {
...element.content,
name: element.name,
package: element.package?.path,
};
}
else if (element instanceof INTERNAL__UnknownPackageableElement) {
this.INTERNAL__unknownElementsIndex.delete(oldPath);
this.INTERNAL__unknownElementsIndex.set(newPath, element);
element.content = {
...element.content,
name: element.name,
package: element.package?.path,
};
}
else if (element instanceof INTERNAL__UnknownFunctionActivator) {
this.functionActivatorsIndex.delete(oldPath);
this.functionActivatorsIndex.set(newPath, element);
element.content = {
...element.content,
name: element.name,
package: element.package?.path,
};
}
else if (element instanceof INTERNAL__UnknownStore) {
this.storesIndex.delete(oldPath);
this.storesIndex.set(newPath, element);
element.content = {
...element.content,
name: element.name,
package: element.package?.path,
};
}
else if (element instanceof Mapping) {
this.mappingsIndex.delete(oldPath);
this.mappingsIndex.set(newPath, element);
}
else if (element instanceof Store) {
this.storesIndex.delete(oldPath);
this.storesIndex.set(newPath, element);
}
else if (element instanceof Type) {
this.typesIndex.delete(oldPath);
this.typesIndex.set(newPath, element);
if (element instanceof Measure) {
if (element.canonicalUnit) {
this.typesIndex.delete(element.canonicalUnit.path);
this.typesIndex.set(element.canonicalUnit.path.replace(oldPath, newPath), element.canonicalUnit);
}
element.nonCanonicalUnits.forEach((unit) => {
this.typesIndex.delete(unit.path);
this.typesIndex.set(unit.path.replace(oldPath, newPath), unit);
});
}
}
else if (element instanceof Association) {
this.associationsIndex.delete(oldPath);
this.associationsIndex.set(newPath, element);
}
else if (element instanceof Profile) {
this.profilesIndex.delete(oldPath);
this.profilesIndex.set(newPath, element);
}
else if (element instanceof ConcreteFunctionDefinition) {
this.functionsIndex.delete(oldPath);
this.functionsIndex.set(newPath, element);
}
else if (element instanceof FunctionActivator) {
this.functionActivatorsIndex.delete(oldPath);
this.functionActivatorsIndex.set(newPath, element);
}
else if (element instanceof Service) {
this.servicesIndex.delete(oldPath);
this.servicesIndex.set(newPath, element);
}
else if (element instanceof PackageableRuntime) {
this.runtimesIndex.delete(oldPath);
this.runtimesIndex.set(newPath, element);
}
else if (element instanceof PackageableConnection) {
this.connectionsIndex.delete(oldPath);
this.connectionsIndex.set(newPath, element);
}
else if (element instanceof FileGenerationSpecification) {
this.fileGenerationsIndex.delete(oldPath);
this.fileGenerationsIndex.set(newPath, element);
}
else if (element instanceof DataElement) {
this.dataElementsIndex.delete(oldPath);
this.dataElementsIndex.set(newPath, element);
}
else if (element instanceof ExecutionEnvironmentInstance) {
this.executionEnvironmentsIndex.delete(oldPath);
this.executionEnvironmentsIndex.set(newPath, element);
}
else if (element instanceof GenerationSpecification) {
this.generationSpecificationsIndex.delete(oldPath);
this.generationSpecificationsIndex.set(newPath, element);
}
else if (element instanceof Package) {
// Since we will modify the package name, we need to first store the original
// paths of all of its children
const childElements = new Map();
element.children.forEach((childElement) => {
childElements.set(childElement.path, childElement);
});
// update element name
element.name = newElementName;
if (!element.package) {
throw new IllegalStateError(`Can't rename root package`);
}
/**
* Update element package if needed.
*
* NOTE: to be clean, first completely remove the package from its parent package
* Only then would we find or create the new parent package. This way, if we rename
* package `example::something` to `example::something::somethingElse`, we will not
* end up in a loop. If we did not first remove the package from its parent package
* we would end up having the `somethingElse` package containing itself as a child.
*/
const currentParentPackage = element.package;
if (currentParentPackage !== this.getNullablePackage(newPackagePath)) {
deleteElementFromPackage(currentParentPackage, element);
const newParentPackage = newPackagePath !== ''
? getOrCreateGraphPackage(this, newPackagePath, undefined)
: this.root;
addElementToPackage(newParentPackage, element);
}
childElements.forEach((childElement, childElementOriginalPath) => {
// NOTE: since we already modified the parent package path, we need to pass in the child element's original path
// here to be sure we're properly, if we rely on the `childElement.path` that would cause a bug
this.renameOwnElement(childElement, childElementOriginalPath, childElementOriginalPath.replace(oldPath, newPath));
});
}
else {
const extension = this.getExtensionForElementClass(getClass(element));
extension.renameElement(oldPath, newPath);
}
}
/**
* TODO: this will be removed once we have full support for section index
* See https://github.com/finos/legend-studio/issues/1067
*/
TEMPORARY__deleteOwnSectionIndex() {
this.sectionIndicesIndex.forEach((sectionIndex) => {
sectionIndex.setIsDeleted(true);
this.sectionIndicesIndex.delete(sectionIndex.path);
});
// NOTE: we have to do this because right now we don't add section index to the package tree
// as such `this.sectionIndicesIndex.delete(sectionIndex.path)` won't work because the path
// is without the package
this.sectionIndicesIndex = new Map();
this.elementSectionIndex = new Map();
}
}
//# sourceMappingURL=BasicModel.js.map