UNPKG

@finos/legend-graph

Version:
122 lines 5.39 kB
/** * 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 { assertNonEmptyString, AssertionError, guaranteeNonNullable, } from '@finos/legend-shared'; import { DependencyModel } from '../../../../../../../graph/DependencyManager.js'; import { LegendSDLC } from '../../../../../../../graph/GraphDataOrigin.js'; import { addElementToPackage, getElementOrigin, getOrCreateGraphPackage, } from '../../../../../../../graph/helpers/DomainHelper.js'; import { GenerationModel, SystemModel, } from '../../../../../../../graph/PureModel.js'; import { V1_buildFullPath, } from './V1_GraphBuilderContext.js'; import { GAV_DELIMITER } from '@finos/legend-storage'; const currentSubGraphOrigin = (graph) => { if (graph instanceof SystemModel) { return 'System elements'; } else if (graph instanceof GenerationModel) { return 'Generation elements'; } else if (graph instanceof DependencyModel && graph.origin instanceof LegendSDLC) { return `Project dependency ${graph.origin.groupId}${GAV_DELIMITER}${graph.origin.artifactId} `; } return ''; }; export const V1_checkDuplicatedElement = (path, context, cache) => { if (cache) { if (cache.has(path)) { const element = context.graph.getNullableElement(path); const _origin = getElementOrigin(guaranteeNonNullable(element), context.graph); throw new AssertionError(`${currentSubGraphOrigin(context.currentSubGraph)}Element '${path}' already exists${_origin ? ` in ${_origin}` : ''}`); } else { cache.add(path); } } else { const element = context.graph.getNullableElement(path); if (element) { const _origin = getElementOrigin(element, context.graph); throw new AssertionError(`${currentSubGraphOrigin(context.currentSubGraph)}Element '${path}' already exists${_origin ? ` in ${_origin}` : ''}`); } } }; /** * Element builder is a mechanism to handling the building process of * element. * - Each builder focuses on only 1 element type. * - Each builder specifies prerequisites element types so that while * building the Pure graph, we can order the builders appropriately. * - Each builder has 5 passes. NOTE: not all elements require 5-pass * building process. But this should give enough flexibility on how * elements can be processed. * * NOTE: we aim to have the first pass to be relatively simple: just build * the basic element, index it and put it in the element tree based on its * path. Since this common task is required by many other builder processes, * the first pass will be run first and separately from other passes. * * Also note that as of right now we will run build pass 2-5 of each element * consecutively so there is no opportunity to `interleave` build passes of * different elements. That definitely seems more flexible, but also incur * a fair amount of complexity we don't see the need for right now. */ export class V1_ElementBuilder { elementClassName; _class; prerequisites = []; firstPass; secondPass; thirdPass; fourthPass; fifthPass; constructor(props) { this.elementClassName = props.elementClassName; this._class = props._class; this.prerequisites = props.prerequisites ?? []; this.firstPass = props.firstPass; this.secondPass = props.secondPass; this.thirdPass = props.thirdPass; this.fourthPass = props.fourthPass; this.fifthPass = props.fifthPass; } getElementProtocolClass() { return this._class; } getPrerequisiteElementProtocolClasses() { return this.prerequisites; } runFirstPass(elementProtocol, context, packageCache, elementPathCache) { assertNonEmptyString(elementProtocol.package, `Element 'package' field is missing or empty`); assertNonEmptyString(elementProtocol.name, `Element 'name' field is missing or empty`); const path = V1_buildFullPath(elementProtocol.package, elementProtocol.name); V1_checkDuplicatedElement(path, context, elementPathCache); const element = this.firstPass(elementProtocol, context); addElementToPackage(getOrCreateGraphPackage(context.currentSubGraph, elementProtocol.package, packageCache), element); return element; } runSecondPass(elementProtocol, context) { this.secondPass?.(elementProtocol, context); } runThirdPass(elementProtocol, context) { this.thirdPass?.(elementProtocol, context); } runFourthPass(elementProtocol, context) { this.fourthPass?.(elementProtocol, context); } runFifthPass(elementProtocol, context) { this.fifthPass?.(elementProtocol, context); } } //# sourceMappingURL=V1_ElementBuilder.js.map