UNPKG

@finos/legend-studio

Version:
279 lines (264 loc) 9.68 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 { observable, action, flow, makeObservable } from 'mobx'; import { EditorState } from './EditorState.js'; import { type GeneratorFn, assertErrorThrown, LogEvent, UnsupportedOperationError, isNonNullable, } from '@finos/legend-shared'; import { LEGEND_STUDIO_APP_EVENT } from '../LegendStudioAppEvent.js'; import type { EditorStore } from '../EditorStore.js'; import type { Entity } from '@finos/legend-model-storage'; import { type ImportConfigurationDescription, ImportMode, } from '@finos/legend-graph'; import { TAB_SIZE } from '@finos/legend-application'; import type { ModelLoaderExtensionConfiguration, LegendStudioApplicationPlugin, } from '../LegendStudioApplicationPlugin.js'; export enum MODEL_UPDATER_INPUT_TYPE { ENTITIES = 'ENTITIES', PURE_PROTOCOL = 'PURE_PROTOCOL', PURE_GRAMMAR = 'PURE_GRAMMAR', } export class ModelLoaderState extends EditorState { modelText = this.getExampleEntitiesInputText(); currentModelLoadType: MODEL_UPDATER_INPUT_TYPE | string = MODEL_UPDATER_INPUT_TYPE.ENTITIES; // TODO: remove model import in favor of external formats modelImportDescriptions: ImportConfigurationDescription[] = []; modelLoaderExtensionConfigurations: ModelLoaderExtensionConfiguration[] = []; replace = true; isLoadingModel = false; constructor(editorStore: EditorStore) { super(editorStore); makeObservable(this, { modelText: observable, currentModelLoadType: observable, modelImportDescriptions: observable, modelLoaderExtensionConfigurations: observable, replace: observable, isLoadingModel: observable, setReplaceFlag: action, setModelText: action, loadCurrentProjectEntities: flow, loadModel: flow, fetchAvailableModelImportDescriptions: flow, }); //extensions this.modelLoaderExtensionConfigurations = this.editorStore.pluginManager .getApplicationPlugins() .flatMap( (plugin: LegendStudioApplicationPlugin) => plugin.getExtraModelLoaderExtensionConfigurations?.() ?? [], ) .filter(isNonNullable); } get headerName(): string { return 'Model Loader'; } getImportConfigurationDescription( key: string, ): ImportConfigurationDescription | undefined { return this.modelImportDescriptions.find((i) => i.key === key); } getLoaderExtensionConfiguration( key: string, ): ModelLoaderExtensionConfiguration | undefined { return this.modelLoaderExtensionConfigurations.find( (i) => i.modelGenerationConfig.key === key, ); } setReplaceFlag(val: boolean): void { this.replace = val; } setModelText(modelText: string): void { this.modelText = modelText; } setCurrentModelLoadType( modelLoadType: MODEL_UPDATER_INPUT_TYPE | string, ): void { if (modelLoadType !== this.currentModelLoadType) { this.currentModelLoadType = modelLoadType; this.modelText = this.getExampleText(modelLoadType); } } getExampleText(inputType: MODEL_UPDATER_INPUT_TYPE | string): string { if (inputType === MODEL_UPDATER_INPUT_TYPE.PURE_PROTOCOL) { return this.getExamplePureProtocolInputText(); } else if (inputType === MODEL_UPDATER_INPUT_TYPE.ENTITIES) { return this.getExampleEntitiesInputText(); } else if (this.getImportConfigurationDescription(inputType)) { return this.getExampleExternalFormatInputText(); } return ''; } /** * Current project entities will be taken from the current graph * If graph is not parsable, we will fall back to model loader */ *loadCurrentProjectEntities(): GeneratorFn<void> { switch (this.currentModelLoadType) { case MODEL_UPDATER_INPUT_TYPE.PURE_PROTOCOL: { const graphEntities = this.editorStore.graphManagerState.graphBuildState .hasSucceeded ? this.editorStore.graphManagerState.graph.allOwnElements.map( (element) => this.editorStore.graphManagerState.graphManager.elementToEntity( element, ), ) : this.editorStore.changeDetectionState .workspaceLocalLatestRevisionState.entities; this.modelText = (yield this.editorStore.graphManagerState.graphManager.entitiesToPureProtocolText( graphEntities, )) as string; break; } case MODEL_UPDATER_INPUT_TYPE.ENTITIES: { const graphEntities = this.editorStore.graphManagerState.graphBuildState .hasSucceeded ? this.editorStore.graphManagerState.graph.allOwnElements.map( (element) => this.editorStore.graphManagerState.graphManager.elementToEntity( element, ), ) : this.editorStore.changeDetectionState .workspaceLocalLatestRevisionState.entities; this.modelText = JSON.stringify(graphEntities, undefined, TAB_SIZE); break; } case MODEL_UPDATER_INPUT_TYPE.PURE_GRAMMAR: { this.modelText = (yield this.editorStore.graphManagerState.graphManager.graphToPureCode( this.editorStore.graphManagerState.graph, )) as string; break; } default: throw new UnsupportedOperationError( `Can't load current project entities for input type of type '${this.currentModelLoadType}'`, ); } } *loadModel(): GeneratorFn<void> { try { this.isLoadingModel = true; this.editorStore.setBlockingAlert({ message: 'Loading model...', prompt: 'Please do not close the application', showLoading: true, }); let entities: Entity[]; const externalConfigType = this.getImportConfigurationDescription( this.currentModelLoadType, ); if (externalConfigType) { entities = (yield this.editorStore.graphManagerState.graphManager.externalFormatTextToEntities( this.modelText, externalConfigType.key, ImportMode.SCHEMA_IMPORT, )) as Entity[]; } else { switch (this.currentModelLoadType) { case MODEL_UPDATER_INPUT_TYPE.PURE_PROTOCOL: { entities = this.editorStore.graphManagerState.graphManager.pureProtocolTextToEntities( this.modelText, ); break; } case MODEL_UPDATER_INPUT_TYPE.ENTITIES: { entities = JSON.parse(this.modelText) as Entity[]; break; } case MODEL_UPDATER_INPUT_TYPE.PURE_GRAMMAR: { entities = (yield this.editorStore.graphManagerState.graphManager.pureCodeToEntities( this.modelText, )) as Entity[]; break; } default: throw new UnsupportedOperationError( `Can't load model for input of type '${this.currentModelLoadType}'`, ); } } const message = `loading entities from ${ this.editorStore.applicationStore.config.appName } [${this.replace ? `potentially affected ` : ''} ${ entities.length } entities]`; yield this.editorStore.sdlcServerClient.updateEntities( this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace, { replace: this.replace, entities, message }, ); this.editorStore.applicationStore.navigator.reload(); } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.MODEL_LOADER_FAILURE), error, ); this.editorStore.applicationStore.notifyError(error); } finally { this.isLoadingModel = false; this.editorStore.setBlockingAlert(undefined); } } *fetchAvailableModelImportDescriptions(): GeneratorFn<void> { try { this.modelImportDescriptions = (yield this.editorStore.graphManagerState.graphManager.getAvailableImportConfigurationDescriptions()) as ImportConfigurationDescription[]; } catch (error) { assertErrorThrown(error); this.editorStore.applicationStore.log.error( LogEvent.create(LEGEND_STUDIO_APP_EVENT.MODEL_LOADER_FAILURE), error, ); this.editorStore.applicationStore.notifyError(error); } } private getExampleEntitiesInputText(): string { return `// example entity\n${JSON.stringify( [ { classifierPath: 'string', content: {}, path: 'string', } as Entity, ], undefined, TAB_SIZE, )}`; } private getExamplePureProtocolInputText(): string { return `// example Pure model context data\n${this.editorStore.graphManagerState.graphManager.getExamplePureProtocolText()}`; } private getExampleExternalFormatInputText(): string { return `// example external format import data\n${this.editorStore.graphManagerState.graphManager.getExampleExternalFormatImportText()}`; } }