@finos/legend-studio
Version:
217 lines • 9.98 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, makeAutoObservable } from 'mobx';
import { LEGEND_STUDIO_APP_EVENT } from '../LegendStudioAppEvent.js';
import { GenerationDirectory, GENERATION_FILE_ROOT_NAME, getGenerationTreeData, openNode, populateDirectoryTreeNodeChildren, buildGenerationDirectory, reprocessOpenNodes, } from '../shared/FileGenerationTreeUtil.js';
import { assertErrorThrown, deepEqual, isEmpty, LogEvent, } from '@finos/legend-shared';
import { ConfigurationProperty, GenerationPropertyItemType, PackageableElement, PackageableElementReference, PackageableElementExplicitReference, ELEMENT_PATH_DELIMITER, getNullableFileGenerationConfig, } from '@finos/legend-graph';
import { configurationProperty_setValue, fileGeneration_addConfigurationProperty, fileGeneration_addScopeElement, fileGeneration_deleteScopeElement, } from '../graphModifier/DSLGeneration_GraphModifierHelper.js';
export class FileGenerationState {
editorStore;
fileGeneration;
isGenerating = false;
root;
directoryTreeData;
selectedNode;
filesIndex = new Map();
constructor(editorStore, fileGeneration) {
makeAutoObservable(this, {
editorStore: false,
fileGeneration: false,
directoryTreeData: observable.ref,
selectedNode: observable.ref,
resetFileGeneration: action,
setIsGeneration: action,
setDirectoryTreeData: action,
processGenerationResult: action,
reprocessNodeTree: action,
setSelectedNode: action,
onTreeNodeSelect: action,
addScopeElement: action,
deleteScopeElement: action,
updateFileGenerationParameters: action,
});
this.editorStore = editorStore;
this.fileGeneration = fileGeneration;
this.root = new GenerationDirectory(GENERATION_FILE_ROOT_NAME);
}
resetFileGeneration() {
this.fileGeneration.configurationProperties = [];
}
setIsGeneration(isGenerating) {
this.isGenerating = isGenerating;
}
setDirectoryTreeData(directoryTreeData) {
this.directoryTreeData = directoryTreeData;
}
getOrCreateDirectory = (directoryName) => GenerationDirectory.getOrCreateDirectory(this.root, directoryName, true);
*generate() {
this.isGenerating = true;
try {
// avoid wasting a network call when the scope is empty, we can short-circuit this
if (!this.fileGeneration.scopeElements.length) {
this.selectedNode = undefined;
this.processGenerationResult([]);
return;
}
const mode = this.editorStore.graphState.graphGenerationState.getFileGenerationConfiguration(this.fileGeneration.type).generationMode;
const result = (yield this.editorStore.graphManagerState.graphManager.generateFile(this.fileGeneration, mode, this.editorStore.graphManagerState.graph));
this.processGenerationResult(result);
}
catch (error) {
assertErrorThrown(error);
this.selectedNode = undefined;
this.processGenerationResult([]);
this.editorStore.applicationStore.log.error(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERATION_FAILURE), error);
this.editorStore.applicationStore.notifyError(error);
}
finally {
this.isGenerating = false;
}
}
processGenerationResult(output) {
this.root = new GenerationDirectory(GENERATION_FILE_ROOT_NAME);
this.filesIndex = new Map();
const openedNodeIds = this.directoryTreeData
? Array.from(this.directoryTreeData.nodes.values())
.filter((node) => node.isOpen)
.map((node) => node.id)
: [];
const generationResultIndex = new Map();
const rootFolder = this.fileGeneration.generationOutputPath ??
this.fileGeneration.path.split(ELEMENT_PATH_DELIMITER).join('_');
output.forEach((entry) => {
entry.cleanFileName(rootFolder);
if (generationResultIndex.has(entry.fileName)) {
this.editorStore.applicationStore.log.warn(LogEvent.create(LEGEND_STUDIO_APP_EVENT.GENERATION_FAILURE), 'Found 2 generation outputs with same path');
}
generationResultIndex.set(entry.fileName, {
generationOutput: entry,
parentId: this.fileGeneration.path,
});
});
// take generation outputs and put them into the root directory
buildGenerationDirectory(this.root, generationResultIndex, this.filesIndex);
this.directoryTreeData = getGenerationTreeData(this.root);
this.reprocessNodeTree(Array.from(generationResultIndex.values()), this.directoryTreeData, openedNodeIds);
}
reprocessNodeTree(generationResult, treeData, openedNodeIds) {
reprocessOpenNodes(treeData, this.filesIndex, this.root, openedNodeIds);
// select the current file node if available, else select the first output
const selectedFileNodePath = generationResult.length === 1 ||
(this.selectedNode === undefined && generationResult.length !== 0)
? generationResult[0].generationOutput
.fileName
: this.selectedNode?.fileNode.path;
if (selectedFileNodePath) {
const file = this.filesIndex.get(selectedFileNodePath);
if (file) {
const node = openNode(file, treeData);
if (node) {
this.onTreeNodeSelect(node, treeData);
}
}
else {
this.selectedNode = undefined;
}
}
this.setDirectoryTreeData({ ...treeData });
}
setSelectedNode(node) {
if (this.selectedNode) {
this.selectedNode.isSelected = false;
}
if (node) {
node.isSelected = true;
}
this.selectedNode = node;
}
onTreeNodeSelect(node, treeData) {
if (node.childrenIds?.length) {
node.isOpen = !node.isOpen;
if (node.fileNode instanceof GenerationDirectory) {
populateDirectoryTreeNodeChildren(node, treeData);
}
}
this.setSelectedNode(node);
this.setDirectoryTreeData({ ...treeData });
}
getScopeElement(element) {
return this.fileGeneration.scopeElements.find((el) => el instanceof PackageableElementReference
? el.value === element
: element === el);
}
addScopeElement(element) {
const el = this.getScopeElement(element);
if (!el) {
fileGeneration_addScopeElement(this.fileGeneration, element instanceof PackageableElement
? PackageableElementExplicitReference.create(element)
: element);
}
}
deleteScopeElement(element) {
const el = this.getScopeElement(element);
if (el) {
fileGeneration_deleteScopeElement(this.fileGeneration, el);
}
}
updateFileGenerationParameters(fileGeneration, generationProperty, newValue) {
if (generationProperty.type === GenerationPropertyItemType.MAP) {
if (!newValue ||
isEmpty(newValue) ||
deepEqual(newValue, generationProperty.defaultValue)) {
fileGeneration.configurationProperties =
fileGeneration.configurationProperties.filter((e) => e.name !== generationProperty.name);
}
else {
const configProperty = getNullableFileGenerationConfig(fileGeneration, generationProperty.name);
if (configProperty) {
configurationProperty_setValue(configProperty, {
...newValue,
});
}
else {
const newItem = new ConfigurationProperty(generationProperty.name, newValue);
fileGeneration_addConfigurationProperty(fileGeneration, newItem);
}
}
}
else {
const configProperty = getNullableFileGenerationConfig(fileGeneration, generationProperty.name);
let useDefaultValue = generationProperty.defaultValue === newValue;
if (generationProperty.type === GenerationPropertyItemType.BOOLEAN) {
useDefaultValue =
(generationProperty.defaultValue === 'true') ===
newValue;
}
const newConfigValue = useDefaultValue ? undefined : newValue;
if (newConfigValue !== undefined) {
if (configProperty) {
configurationProperty_setValue(configProperty, newConfigValue);
}
else {
const newItem = new ConfigurationProperty(generationProperty.name, newConfigValue);
fileGeneration_addConfigurationProperty(fileGeneration, newItem);
}
}
else {
fileGeneration.configurationProperties =
fileGeneration.configurationProperties.filter((e) => e.name !== generationProperty.name);
}
}
}
}
//# sourceMappingURL=FileGenerationState.js.map