@finos/legend-application-studio
Version:
Legend Studio application core
449 lines • 20.9 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 { observable, action, flow, makeObservable, computed, flowResult, } from 'mobx';
import { EditorState } from './EditorState.js';
import { assertErrorThrown, LogEvent, UnsupportedOperationError, isNonNullable, ActionState, assertTrue, } from '@finos/legend-shared';
import { LEGEND_STUDIO_APP_EVENT } from '../../../__lib__/LegendStudioEvent.js';
import { generateGAVCoordinates } from '@finos/legend-storage';
import { DEFAULT_TAB_SIZE } from '@finos/legend-application';
import { GraphEntities, LegendSDLC, SchemaSet, observe_SchemaSet, } from '@finos/legend-graph';
import { externalFormat_schemaSet_setFormat, externalFormat_schemaSet_setSchemas, } from '../../graph-modifier/DSL_ExternalFormat_GraphModifierHelper.js';
import { InnerSchemaSetEditorState } from './element-editor-state/external-format/DSL_ExternalFormat_SchemaSetEditorState.js';
import { ProjectDependency, UpdateProjectConfigurationCommand, } from '@finos/legend-server-sdlc';
import { generateEditorRoute } from '../../../__lib__/LegendStudioNavigation.js';
export var MODEL_IMPORT_NATIVE_INPUT_TYPE;
(function (MODEL_IMPORT_NATIVE_INPUT_TYPE) {
MODEL_IMPORT_NATIVE_INPUT_TYPE["ENTITIES"] = "ENTITIES";
MODEL_IMPORT_NATIVE_INPUT_TYPE["PURE_PROTOCOL"] = "PURE_PROTOCOL";
MODEL_IMPORT_NATIVE_INPUT_TYPE["PURE_GRAMMAR"] = "PURE_GRAMMAR";
})(MODEL_IMPORT_NATIVE_INPUT_TYPE || (MODEL_IMPORT_NATIVE_INPUT_TYPE = {}));
export var MODEL_IMPORT_TYPE;
(function (MODEL_IMPORT_TYPE) {
MODEL_IMPORT_TYPE["NATIVE"] = "NATIVE";
MODEL_IMPORT_TYPE["EXTERNAL_FORMAT"] = "EXTERNAL_FORMAT";
MODEL_IMPORT_TYPE["EXTENSIONS"] = "EXTENSIONS";
})(MODEL_IMPORT_TYPE || (MODEL_IMPORT_TYPE = {}));
export class ModelImporterEditorState {
editorStore;
modelImporterState;
loadModelActionState = ActionState.create();
constructor(modelImporterState) {
this.editorStore = modelImporterState.editorStore;
this.modelImporterState = modelImporterState;
}
}
export class NativeModelImporterEditorState extends ModelImporterEditorState {
nativeType = MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES;
modelText;
loadCurrentProjectActionState = ActionState.create();
constructor(modelImporterState) {
super(modelImporterState);
makeObservable(this, {
nativeType: observable,
modelText: observable,
loadModelActionState: observable,
setModelText: action,
setNativeImportType: action,
isLoadingDisabled: computed,
loadCurrentProjectEntities: flow,
});
this.modelText = this.getExampleEntitiesInputText();
}
get label() {
return this.nativeType;
}
get allowHardReplace() {
return true;
}
get isLoadingDisabled() {
return this.loadCurrentProjectActionState.isInProgress;
}
setModelText(val) {
this.modelText = val;
}
setNativeImportType(nativeImportType) {
if (this.nativeType !== nativeImportType) {
this.nativeType = nativeImportType;
this.modelText = this.getNativeImportExampleText(nativeImportType);
}
}
getNativeImportExampleText(inputType) {
switch (inputType) {
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_PROTOCOL:
return this.getExamplePureProtocolInputText();
case MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES:
return this.getExampleEntitiesInputText();
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_GRAMMAR:
return this.getExamplePureGrammarText();
default:
return '';
}
}
async loadEntites() {
switch (this.nativeType) {
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_PROTOCOL: {
return this.editorStore.graphManagerState.graphManager.pureProtocolTextToEntities(this.modelText);
}
case MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES: {
return JSON.parse(this.modelText);
}
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_GRAMMAR: {
return this.editorStore.graphManagerState.graphManager.pureCodeToEntities(this.modelText);
}
default:
throw new UnsupportedOperationError(`Can't load model for input of type '${this.nativeType}'`);
}
}
*loadCurrentProjectEntities() {
this.loadCurrentProjectActionState.inProgress();
switch (this.nativeType) {
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_PROTOCOL: {
const graphEntities = this.editorStore.graphManagerState.graphBuildState
.hasSucceeded
? this.editorStore.graphManagerState.graph.knownAllOwnElements.map((element) => this.editorStore.graphManagerState.graphManager.elementToEntity(element))
: this.editorStore.changeDetectionState
.workspaceLocalLatestRevisionState.entities;
this.modelText =
(yield this.editorStore.graphManagerState.graphManager.entitiesToPureProtocolText(graphEntities));
break;
}
case MODEL_IMPORT_NATIVE_INPUT_TYPE.ENTITIES: {
const graphEntities = this.editorStore.graphManagerState.graphBuildState
.hasSucceeded
? this.editorStore.graphManagerState.graph.knownAllOwnElements.map((element) => this.editorStore.graphManagerState.graphManager.elementToEntity(element))
: this.editorStore.changeDetectionState
.workspaceLocalLatestRevisionState.entities;
this.modelText = JSON.stringify(graphEntities, undefined, DEFAULT_TAB_SIZE);
break;
}
case MODEL_IMPORT_NATIVE_INPUT_TYPE.PURE_GRAMMAR: {
this.modelText =
(yield this.editorStore.graphManagerState.graphManager.graphToPureCode(this.editorStore.graphManagerState.graph, { excludeUnknown: true }));
break;
}
default:
this.loadCurrentProjectActionState.fail();
throw new UnsupportedOperationError(`Can't load current project entities for input type of type '${this.nativeType}'`);
}
this.loadCurrentProjectActionState.complete();
}
getExampleEntitiesInputText() {
return `${JSON.stringify([
{
classifierPath: 'string',
content: {},
path: 'string',
},
], undefined, DEFAULT_TAB_SIZE)}`;
}
getExamplePureProtocolInputText() {
return `${this.editorStore.graphManagerState.graphManager.getExamplePureProtocolText()}`;
}
getExamplePureGrammarText() {
return `###Pure\n Class model::A\n {\n\n}`;
}
async loadModel() {
try {
this.loadModelActionState.inProgress();
this.editorStore.applicationStore.alertService.setBlockingAlert({
message: 'Loading model...',
prompt: 'Please do not close the application',
showLoading: true,
});
const entities = await this.loadEntites();
const message = `loading entities from ${this.editorStore.applicationStore.config.appName} [${this.modelImporterState.replace ? `potentially affected ` : ''} ${entities.length} entities]`;
await this.editorStore.sdlcServerClient.updateEntities(this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace, { replace: this.modelImporterState.replace, entities, message });
this.editorStore.applicationStore.navigationService.navigator.reload({
ignoreBlocking: true,
});
}
catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.MODEL_LOADER_FAILURE), error);
this.editorStore.applicationStore.notificationService.notifyError(error);
}
finally {
this.loadModelActionState.complete();
this.editorStore.applicationStore.alertService.setBlockingAlert(undefined);
}
}
}
export class ExecuteInputDebugModelImporterEditorState extends ModelImporterEditorState {
executeInput = '{}';
executablePath = 'test::Debugger';
loadState = ActionState.create();
constructor(modelImporterState) {
super(modelImporterState);
makeObservable(this, {
executeInput: observable,
setExecuteInput: action,
executablePath: observable,
setExecutablePath: action,
});
}
get label() {
return `Execute Input [DEBUG]`;
}
get allowHardReplace() {
return false;
}
get isLoadingDisabled() {
return this.loadState.isInProgress;
}
setExecuteInput(val) {
this.executeInput = val;
}
setExecutablePath(val) {
this.executablePath = val;
}
async loadModel() {
this.loadModelActionState.inProgress();
try {
this.editorStore.applicationStore.alertService.setBlockingAlert({
message: 'Loading model...',
prompt: 'Please do not close the application',
showLoading: true,
});
const result = await this.editorStore.graphManagerState.graphManager.analyzeExecuteInput(JSON.parse(this.executeInput), this.executablePath);
let entities = [];
let dependencies = [];
if (result.origin instanceof GraphEntities) {
entities = [...result.origin.entities, ...result.entities];
}
else if (result.origin instanceof LegendSDLC) {
entities = [...result.entities];
dependencies = [
new ProjectDependency(generateGAVCoordinates(result.origin.groupId, result.origin.artifactId, undefined), result.origin.versionId),
];
}
const message = `loading entities from ${this.editorStore.applicationStore.config.appName} [${this.modelImporterState.replace ? `potentially affected ` : ''} ${entities.length} entities]`;
await this.editorStore.sdlcServerClient.updateEntities(this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace, { replace: this.modelImporterState.replace, entities, message });
const currentProjectConfiguration = this.editorStore.projectConfigurationEditorState.originalConfig;
const updateProjectConfigurationCommand = new UpdateProjectConfigurationCommand(currentProjectConfiguration.groupId, currentProjectConfiguration.artifactId, currentProjectConfiguration.projectStructureVersion, `update project configuration from ${this.editorStore.applicationStore.config.appName}`);
updateProjectConfigurationCommand.projectDependenciesToAdd = dependencies;
updateProjectConfigurationCommand.projectDependenciesToRemove =
currentProjectConfiguration.projectDependencies;
await flowResult(this.editorStore.projectConfigurationEditorState.updateProjectConfiguration(updateProjectConfigurationCommand));
// open the debugger element
this.editorStore.applicationStore.navigationService.navigator.goToLocation(generateEditorRoute(this.editorStore.sdlcState.activeProject.projectId, undefined, this.editorStore.sdlcState.activeWorkspace.workspaceId, this.editorStore.sdlcState.activeWorkspace.workspaceType, this.executablePath), {
ignoreBlocking: true,
});
}
catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.logService.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.MODEL_LOADER_FAILURE), error);
this.editorStore.applicationStore.notificationService.notifyError(error);
}
finally {
this.loadModelActionState.complete();
this.editorStore.applicationStore.alertService.setBlockingAlert(undefined);
}
}
}
export class ExtensionModelImportRendererState {
importerState;
constructor(importerState) {
this.importerState = importerState;
}
}
export class ExtensionModelImporterEditorState extends ModelImporterEditorState {
config;
rendererState;
constructor(config, rendererState, modelImporterState) {
super(modelImporterState);
makeObservable(this, {
config: observable,
modelImporterState: observable,
loadModelActionState: observable,
rendererState: observable,
isLoadingDisabled: computed,
setExtension: action,
loadModel: flow,
});
this.config = config;
this.rendererState = rendererState;
}
get label() {
return this.config.label ?? this.config.key;
}
get allowHardReplace() {
return Boolean(this.config.allowHardReplace);
}
get isLoadingDisabled() {
return false;
}
setExtension(extensionConfiguration) {
this.config = extensionConfiguration;
}
async loadModel() {
await this.config.loadModel(this.rendererState);
}
}
const DEFAULT_SCHEMA_PACKAGE = '__internal__';
const DEFAULT_SCHEMA_NAME = 'MyShemaSet';
export class ExternalFormatModelImporterState extends ModelImporterEditorState {
schemaSet;
schemaSetEditorState;
description;
isolatedSchemaGraph;
constructor(description, modelImporterState) {
super(modelImporterState);
makeObservable(this, {
schemaSet: observable,
schemaSetEditorState: observable,
loadModelActionState: observable,
description: observable,
isolatedSchemaGraph: observable,
setExternalFormat: action,
setDescription: action,
isLoadingDisabled: computed,
});
this.description = description;
this.schemaSet = new SchemaSet(DEFAULT_SCHEMA_NAME);
this.schemaSet.format = description.name;
observe_SchemaSet(this.schemaSet);
const emptyGraph = this.editorStore.graphManagerState.createNewGraph();
emptyGraph.addElement(this.schemaSet, DEFAULT_SCHEMA_PACKAGE);
this.isolatedSchemaGraph = emptyGraph;
this.schemaSetEditorState = new InnerSchemaSetEditorState(false, this.schemaSet, this.editorStore, this.isolatedSchemaGraph);
}
get allowHardReplace() {
return true;
}
get label() {
return this.schemaSet.format;
}
get isLoadingDisabled() {
return (!this.schemaSetEditorState.schemaSetModelGenerationState.canGenerate ||
this.schemaSetEditorState.schemaSetModelGenerationState
.generatingModelsState.isInProgress ||
this.schemaSetEditorState.schemaSetModelGenerationState
.importGeneratedElementsState.isInProgress);
}
setDescription(val) {
this.description = val;
}
setExternalFormat(description) {
if (description !== this.description) {
this.setDescription(description);
externalFormat_schemaSet_setFormat(this.schemaSet, this.description.name);
externalFormat_schemaSet_setSchemas(this.schemaSet, []);
this.schemaSetEditorState.reset();
}
}
async loadModel() {
this.loadModelActionState.inProgress();
try {
this.loadModelActionState.inProgress();
this.editorStore.applicationStore.alertService.setBlockingAlert({
message: 'Loading model...',
prompt: 'Please do not close the application',
showLoading: true,
});
const modelgenerationstate = this.schemaSetEditorState.schemaSetModelGenerationState;
const entities = await flowResult(modelgenerationstate.getImportEntities());
if (modelgenerationstate.targetBinding) {
const schemaEntity = this.editorStore.graphManagerState.graphManager.elementToEntity(this.schemaSet);
entities.push(schemaEntity);
}
assertTrue(Boolean(entities.length), 'No entities to load');
const message = `loading entities from ${this.editorStore.applicationStore.config.appName} [${this.modelImporterState.replace ? `potentially affected ` : ''} ${entities.length} entities]`;
await this.editorStore.sdlcServerClient.updateEntities(this.editorStore.sdlcState.activeProject.projectId, this.editorStore.sdlcState.activeWorkspace, { replace: this.modelImporterState.replace, entities, message });
this.editorStore.applicationStore.navigationService.navigator.reload({
ignoreBlocking: true,
});
}
catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.notificationService.notifyError(error);
}
finally {
this.loadModelActionState.complete();
this.editorStore.applicationStore.alertService.setBlockingAlert(undefined);
}
}
}
export class ModelImporterState extends EditorState {
replace = true;
modelImportEditorState;
extensionConfigs = [];
constructor(editorStore) {
super(editorStore);
makeObservable(this, {
replace: observable,
modelImportEditorState: observable,
extensionConfigs: observable,
setReplaceFlag: action,
setModelImporterExtension: action,
setNativeImportType: action,
setExternalFormatImportFormat: action,
setImportEditorState: action,
});
this.modelImportEditorState = new NativeModelImporterEditorState(this);
this.extensionConfigs = this.editorStore.pluginManager
.getApplicationPlugins()
.flatMap((plugin) => plugin.getExtraModelImporterExtensionConfigurations?.() ?? [])
.filter(isNonNullable);
}
get label() {
return 'Model Importer';
}
match(tab) {
return tab instanceof ModelImporterState;
}
setReplaceFlag(val) {
this.replace = val;
}
setImportEditorState(val) {
this.modelImportEditorState = val;
}
setNativeImportType(nativeImportType) {
const nativeEditorState = this.modelImportEditorState instanceof NativeModelImporterEditorState
? this.modelImportEditorState
: new NativeModelImporterEditorState(this);
nativeEditorState.setNativeImportType(nativeImportType);
this.setImportEditorState(nativeEditorState);
return nativeEditorState;
}
setExternalFormatImportFormat(externalFormat) {
const extensionEditorState = this.modelImportEditorState instanceof ExternalFormatModelImporterState
? this.modelImportEditorState
: new ExternalFormatModelImporterState(externalFormat, this);
extensionEditorState.setExternalFormat(externalFormat);
this.setImportEditorState(extensionEditorState);
return extensionEditorState;
}
setModelImporterExtension(extension) {
if (this.modelImportEditorState instanceof
ExtensionModelImporterEditorState &&
this.modelImportEditorState.config === extension) {
return this.modelImportEditorState;
}
else {
const modelImporterEditorState = new ExtensionModelImporterEditorState(extension, extension.getExtensionModelImportRendererStateCreator(this), this);
this.setImportEditorState(modelImporterEditorState);
return modelImporterEditorState;
}
}
setExecuteInputDebugModelImporter() {
const executeInputDebugModelImporterEditorState = this.modelImportEditorState instanceof
ExecuteInputDebugModelImporterEditorState
? this.modelImportEditorState
: new ExecuteInputDebugModelImporterEditorState(this);
this.setImportEditorState(executeInputDebugModelImporterEditorState);
}
}
//# sourceMappingURL=ModelImporterState.js.map