@finos/legend-extension-dsl-data-space
Version:
Legend extension for Data Space DSL
442 lines • 26.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 packageJson from '../../../../package.json' with { type: 'json' };
import V1_SYSTEM_MODELS from './v1/V1_DSL_DataSpace_SystemModels.json' with { type: 'json' };
import { V1_DataSpace, V1_DataSpaceDiagram, V1_DataSpaceElementPointer, V1_DataSpaceExecutionContext, V1_DataSpacePackageableElementExecutable, V1_DataSpaceSupportCombinedInfo, V1_DataSpaceSupportEmail, V1_DataSpaceTemplateExecutable, } from './v1/model/packageableElements/dataSpace/V1_DSL_DataSpace_DataSpace.js';
import { guaranteeNonEmptyString, guaranteeNonNullable, UnsupportedOperationError, isNonNullable, assertType, guaranteeType, returnUndefOnError, } from '@finos/legend-shared';
import { deserialize } from 'serializr';
import { V1_DATA_SPACE_ELEMENT_PROTOCOL_TYPE, V1_deserializeDataSpace, V1_MAPPING_INCLUDE_DATASPACE_TYPE, V1_serializeDataSpace, V1_serializeMappingInclude, V1_deserializeMappingInclude, } from './v1/transformation/pureProtocol/V1_DSL_DataSpace_ProtocolHelper.js';
import { V1_resolveDataSpace } from './v1/transformation/pureGraph/V1_DSL_DataSpace_GraphBuilderHelper.js';
import { getOwnDataSpace } from '../../DSL_DataSpace_GraphManagerHelper.js';
import { DataSpace, DataSpaceExecutionContext, DataSpaceSupportCombinedInfo, DataSpaceSupportEmail, DataSpaceDiagram, DataSpaceElementPointer, DataSpaceExecutableTemplate, DataSpacePackageableElementExecutable, } from '../../../graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js';
import { V1_taggedValueModelSchema, PackageableElementExplicitReference, V1_PackageableElementPointer, PackageableElementPointerType, V1_buildTaggedValue, V1_transformStereotype, V1_transformTaggedValue, PureProtocolProcessorPlugin, V1_ElementBuilder, V1_initPackageableElement, V1_buildFullPath, Class, Enumeration, Association, Package, V1_RawValueSpecificationTransformer, V1_buildRawLambdaWithResolvedPaths, V1_buildEmbeddedData, V1_transformEmbeddedData, DataElementReference, V1_DataElementReference, QueryDataSpaceExecutionContextInfo, generateFunctionPrettyName, ConcreteFunctionDefinition, } from '@finos/legend-graph';
import { V1_resolveDiagram } from '@finos/legend-extension-dsl-diagram/graph';
import { V1_MappingIncludeDataSpace } from './v1/model/packageableElements/mapping/V1_DSL_DataSpace_MappingIncludeDataSpace.js';
import { MappingIncludeDataSpace } from '../../../graph/metamodel/pure/model/packageableElements/mapping/DSL_DataSpace_MappingIncludeDataSpace.js';
export const DATA_SPACE_ELEMENT_CLASSIFIER_PATH = 'meta::pure::metamodel::dataSpace::DataSpace';
export const DATA_SPACE_ELEMENT_POINTER = 'DATASPACE';
export class DSL_DataSpace_PureProtocolProcessorPlugin extends PureProtocolProcessorPlugin {
constructor() {
super(packageJson.extensions.pureProtocolProcessorPlugin, packageJson.version);
}
V1_getExtraElementBuilders() {
return [
new V1_ElementBuilder({
elementClassName: 'DataSpace',
_class: V1_DataSpace,
firstPass: (elementProtocol, context) => {
assertType(elementProtocol, V1_DataSpace);
const element = new DataSpace(elementProtocol.name);
const path = V1_buildFullPath(elementProtocol.package, elementProtocol.name);
element.executionContexts = guaranteeNonNullable(elementProtocol.executionContexts, `Data product 'executionContexts' field is missing`).map((contextProtocol) => {
const execContext = new DataSpaceExecutionContext();
execContext.name = guaranteeNonEmptyString(contextProtocol.name, `Data product execution context 'name' field is missing or empty`);
execContext.title = contextProtocol.title;
execContext.description = contextProtocol.description;
execContext.mapping = PackageableElementExplicitReference.create(context.graph.getMapping(contextProtocol.mapping.path));
execContext.defaultRuntime =
PackageableElementExplicitReference.create(context.graph.getRuntime(contextProtocol.defaultRuntime.path));
execContext.testData = contextProtocol.testData
? guaranteeType(V1_buildEmbeddedData(contextProtocol.testData, context), DataElementReference)
: undefined;
return execContext;
});
element.defaultExecutionContext = guaranteeNonNullable(element.executionContexts.find((execContext) => execContext.name ===
guaranteeNonEmptyString(elementProtocol.defaultExecutionContext, `Data product 'defaultExecutionContext' field is missing or empty`)), `Can't find default execution context '${elementProtocol.defaultExecutionContext}'`);
context.currentSubGraph.setOwnElementInExtension(path, element, DataSpace);
return element;
},
secondPass: (elementProtocol, context) => {
assertType(elementProtocol, V1_DataSpace);
const path = V1_buildFullPath(elementProtocol.package, elementProtocol.name);
const element = getOwnDataSpace(path, context.currentSubGraph);
element.stereotypes = elementProtocol.stereotypes
.map((stereotype) => context.resolveStereotype(stereotype))
.filter(isNonNullable);
element.taggedValues = elementProtocol.taggedValues
.map((taggedValue) => V1_buildTaggedValue(taggedValue, context))
.filter(isNonNullable);
element.title = elementProtocol.title;
element.description = elementProtocol.description;
if (elementProtocol.elements) {
element.elements = elementProtocol.elements.map((pointer) => {
const elementReference = context.resolveElement(pointer.path, true);
if (elementReference.value instanceof Package ||
elementReference.value instanceof Class ||
elementReference.value instanceof Enumeration ||
elementReference.value instanceof Association) {
const elementPointer = new DataSpaceElementPointer();
elementPointer.element =
elementReference;
elementPointer.exclude = pointer.exclude;
return elementPointer;
}
throw new UnsupportedOperationError(`Can't find data product element (only allow packages, classes, enumerations, and associations) '${pointer.path}'`);
});
}
if (elementProtocol.executables) {
element.executables = elementProtocol.executables.map((executableProtocol) => {
if (executableProtocol instanceof V1_DataSpaceTemplateExecutable) {
const executable = new DataSpaceExecutableTemplate();
if (executableProtocol.id) {
executable.id = executableProtocol.id;
}
executable.title = executableProtocol.title;
executable.description = executableProtocol.description;
executable.query = V1_buildRawLambdaWithResolvedPaths(executableProtocol.query.parameters, executableProtocol.query.body, context);
if (executableProtocol.executionContextKey) {
executable.executionContextKey =
executableProtocol.executionContextKey;
}
return executable;
}
else if (executableProtocol instanceof
V1_DataSpacePackageableElementExecutable) {
const executable = new DataSpacePackageableElementExecutable();
if (executableProtocol.id) {
executable.id = executableProtocol.id;
}
executable.title = executableProtocol.title;
executable.description = executableProtocol.description;
if (executableProtocol.executionContextKey) {
executable.executionContextKey =
executableProtocol.executionContextKey;
}
try {
executable.executable = context.resolveElement(executableProtocol.executable.path, false);
}
catch {
try {
executable.executable =
PackageableElementExplicitReference.create(guaranteeNonNullable(context.graph.functions.find((fn) => generateFunctionPrettyName(fn, {
fullPath: true,
spacing: false,
notIncludeParamName: true,
}) ===
executableProtocol.executable.path.replaceAll(/\s*/gu, ''))));
}
catch {
throw new UnsupportedOperationError(`Can't analyze data product executable with element in path: ${executableProtocol.executable.path}`, executableProtocol);
}
}
return executable;
}
else {
throw new UnsupportedOperationError(`Can't build data product executable`, executableProtocol);
}
});
}
if (elementProtocol.diagrams) {
element.diagrams = elementProtocol.diagrams.map((diagramProtocol) => {
const diagram = new DataSpaceDiagram();
diagram.title = diagramProtocol.title;
diagram.description = diagramProtocol.description;
diagram.diagram = V1_resolveDiagram(diagramProtocol.diagram.path, context);
return diagram;
});
}
if (elementProtocol.supportInfo) {
if (elementProtocol.supportInfo instanceof V1_DataSpaceSupportEmail) {
const supportEmail = new DataSpaceSupportEmail();
supportEmail.documentationUrl =
elementProtocol.supportInfo.documentationUrl;
supportEmail.address = guaranteeNonEmptyString(elementProtocol.supportInfo.address, `Data product support email 'address' field is missing or empty`);
element.supportInfo = supportEmail;
}
else if (elementProtocol.supportInfo instanceof
V1_DataSpaceSupportCombinedInfo) {
const combinedInfo = new DataSpaceSupportCombinedInfo();
combinedInfo.documentationUrl =
elementProtocol.supportInfo.documentationUrl;
combinedInfo.emails = elementProtocol.supportInfo.emails;
combinedInfo.website = elementProtocol.supportInfo.website;
combinedInfo.faqUrl = elementProtocol.supportInfo.faqUrl;
combinedInfo.supportUrl = elementProtocol.supportInfo.supportUrl;
element.supportInfo = combinedInfo;
}
else {
throw new UnsupportedOperationError(`Can't build data product support info`, elementProtocol.supportInfo);
}
}
},
}),
];
}
V1_getExtraSystemModels() {
return [V1_SYSTEM_MODELS];
}
V1_getExtraElementClassifierPathGetters() {
return [
(elementProtocol) => {
if (elementProtocol instanceof V1_DataSpace) {
return DATA_SPACE_ELEMENT_CLASSIFIER_PATH;
}
return undefined;
},
];
}
V1_getExtraElementPointerTypes() {
return [
(elementProtocol) => {
if (elementProtocol instanceof DataSpace) {
return DATA_SPACE_ELEMENT_POINTER;
}
return undefined;
},
];
}
V1_getExtraElementProtocolSerializers() {
return [
(elementProtocol, plugins) => {
if (elementProtocol instanceof V1_DataSpace) {
return V1_serializeDataSpace(elementProtocol);
}
return undefined;
},
];
}
V1_getExtraElementProtocolDeserializers() {
return [
(json, plugins) => {
if (json._type === V1_DATA_SPACE_ELEMENT_PROTOCOL_TYPE) {
return V1_deserializeDataSpace(json);
}
return undefined;
},
];
}
V1_getExtraElementTransformers() {
return [
(metamodel, context) => {
if (metamodel instanceof DataSpace) {
const protocol = new V1_DataSpace();
V1_initPackageableElement(protocol, metamodel);
protocol.stereotypes = metamodel.stereotypes.map(V1_transformStereotype);
protocol.taggedValues = metamodel.taggedValues.map(V1_transformTaggedValue);
protocol.executionContexts = metamodel.executionContexts.map((execContext) => {
const contextProtocol = new V1_DataSpaceExecutionContext();
contextProtocol.name = execContext.name;
contextProtocol.title = execContext.title;
contextProtocol.description = execContext.description;
contextProtocol.mapping = new V1_PackageableElementPointer(PackageableElementPointerType.MAPPING, execContext.mapping.valueForSerialization ?? '');
contextProtocol.defaultRuntime = new V1_PackageableElementPointer(PackageableElementPointerType.RUNTIME, execContext.defaultRuntime.valueForSerialization ?? '');
contextProtocol.testData = execContext.testData
? guaranteeType(V1_transformEmbeddedData(execContext.testData, context), V1_DataElementReference)
: undefined;
return contextProtocol;
});
protocol.defaultExecutionContext =
metamodel.defaultExecutionContext.name;
protocol.title = metamodel.title;
protocol.description = metamodel.description;
protocol.elements = metamodel.elements?.map((pointer) => {
const elementPointer = new V1_DataSpaceElementPointer();
elementPointer.exclude = pointer.exclude;
elementPointer.path = pointer.element.valueForSerialization ?? '';
return elementPointer;
});
protocol.executables = metamodel.executables?.map((executable) => {
if (executable instanceof DataSpaceExecutableTemplate) {
const executableProtocol = new V1_DataSpaceTemplateExecutable();
if (executable.id) {
executableProtocol.id = executable.id;
}
executableProtocol.title = executable.title;
executableProtocol.description = executable.description;
if (executable.executionContextKey) {
executableProtocol.executionContextKey =
executable.executionContextKey;
}
executableProtocol.query =
executable.query.accept_RawValueSpecificationVisitor(new V1_RawValueSpecificationTransformer(context));
return executableProtocol;
}
else if (executable instanceof DataSpacePackageableElementExecutable) {
const executableProtocol = new V1_DataSpacePackageableElementExecutable();
if (executable.id) {
executableProtocol.id = executable.id;
}
executableProtocol.title = executable.title;
executableProtocol.description = executable.description;
if (executable.executionContextKey) {
executableProtocol.executionContextKey =
executable.executionContextKey;
}
if (executable.executable.value instanceof
ConcreteFunctionDefinition) {
executableProtocol.executable =
new V1_PackageableElementPointer(PackageableElementPointerType.FUNCTION, generateFunctionPrettyName(executable.executable.value, {
fullPath: true,
spacing: false,
notIncludeParamName: true,
}));
}
else {
executableProtocol.executable =
new V1_PackageableElementPointer(undefined, executable.executable.valueForSerialization ?? '');
}
return executableProtocol;
}
else {
throw new UnsupportedOperationError(`Can't transform data product executable`, executable);
}
});
protocol.diagrams = metamodel.diagrams?.map((diagram) => {
const diagramProtocol = new V1_DataSpaceDiagram();
diagramProtocol.title = diagram.title;
diagramProtocol.description = diagram.description;
diagramProtocol.diagram = new V1_PackageableElementPointer(undefined, diagram.diagram.valueForSerialization ?? '');
return diagramProtocol;
});
if (metamodel.supportInfo) {
if (metamodel.supportInfo instanceof DataSpaceSupportEmail) {
const supportEmail = new V1_DataSpaceSupportEmail();
supportEmail.documentationUrl =
metamodel.supportInfo.documentationUrl;
supportEmail.address = metamodel.supportInfo.address;
protocol.supportInfo = supportEmail;
}
else if (metamodel.supportInfo instanceof DataSpaceSupportCombinedInfo) {
const combinedInfo = new V1_DataSpaceSupportCombinedInfo();
combinedInfo.documentationUrl =
metamodel.supportInfo.documentationUrl;
combinedInfo.emails = metamodel.supportInfo.emails;
combinedInfo.website = metamodel.supportInfo.website;
combinedInfo.faqUrl = metamodel.supportInfo.faqUrl;
combinedInfo.supportUrl = metamodel.supportInfo.supportUrl;
protocol.supportInfo = combinedInfo;
}
else {
throw new UnsupportedOperationError(`Can't transform data product support info`, metamodel.supportInfo);
}
}
return protocol;
}
return undefined;
},
];
}
V1_getExtraMappingIncludeBuilders() {
return [
(protocol, parentMapping, context) => {
if (protocol instanceof V1_MappingIncludeDataSpace) {
const dataSpace = V1_resolveDataSpace(protocol.includedDataSpace, context);
const includedMapping = new MappingIncludeDataSpace(parentMapping, dataSpace.value.defaultExecutionContext.mapping, dataSpace);
return includedMapping;
}
return undefined;
},
];
}
V1_getExtraMappingIncludeTransformers() {
return [
(metamodel, context) => {
if (metamodel instanceof MappingIncludeDataSpace) {
const mappingInclude = new V1_MappingIncludeDataSpace();
mappingInclude.includedDataSpace =
metamodel.includedDataSpace.valueForSerialization ?? '';
return mappingInclude;
}
return undefined;
},
];
}
V1_getExtraMappingIncludeProtocolSerializers() {
return [
(protocol) => {
if (protocol instanceof V1_MappingIncludeDataSpace) {
return V1_serializeMappingInclude(protocol);
}
return undefined;
},
];
}
V1_getExtraMappingIncludeProtocolDeserializers() {
return [
(json) => {
if (json._type === V1_MAPPING_INCLUDE_DATASPACE_TYPE) {
return V1_deserializeMappingInclude(json);
}
return undefined;
},
];
}
V1_getExtraMappingIncludeIdentifierBuilders() {
return [
(protocol) => {
if (protocol instanceof V1_MappingIncludeDataSpace) {
return protocol.includedDataSpace;
}
return undefined;
},
];
}
V1_getExtraSavedQueryExecutionBuilder() {
return [
(queryExec, entites) => {
if (queryExec instanceof QueryDataSpaceExecutionContextInfo) {
const dataSpace = queryExec.dataSpacePath;
const dataSpaceEntity = entites.find((e) => e.path === dataSpace);
if (dataSpaceEntity) {
const content = dataSpaceEntity.content;
if (content._type === V1_DATA_SPACE_ELEMENT_PROTOCOL_TYPE) {
const v1DataSpace = returnUndefOnError(() => V1_deserializeDataSpace(content));
if (v1DataSpace) {
if (v1DataSpace.executionContexts.length === 1) {
const exec = guaranteeNonNullable(v1DataSpace.executionContexts[0]);
return {
mapping: exec.mapping.path,
runtime: exec.defaultRuntime.path,
};
}
const resvoled = queryExec.executionKey ?? v1DataSpace.defaultExecutionContext;
const resolvedExec = guaranteeNonNullable(v1DataSpace.executionContexts.find((e) => e.name === resvoled));
return {
mapping: resolvedExec.mapping.path,
runtime: resolvedExec.defaultRuntime.path,
};
}
}
}
}
return undefined;
},
];
}
}
export const extractDataSpaceTaxonomyNodes = (json) => {
const ENTERPRISE_PROFILE_PATH = `meta::pure::profiles::enterprise`;
const TAXONOMY_NODES_TAG = `taxonomyNodes`;
const TAXONOMY_NODES_TAG_VALUE_DELIMITER = `,`;
const taxonomyNodes = new Set();
if (json._type === V1_DATA_SPACE_ELEMENT_PROTOCOL_TYPE) {
if (Array.isArray(json.taggedValues)) {
const taggedValues = json.taggedValues.map((taggedValueJson) => deserialize(V1_taggedValueModelSchema, taggedValueJson));
taggedValues
.filter((taggedValue) => taggedValue.tag.profile === ENTERPRISE_PROFILE_PATH &&
taggedValue.tag.value === TAXONOMY_NODES_TAG)
.forEach((taggedValue) => {
taggedValue.value
.split(TAXONOMY_NODES_TAG_VALUE_DELIMITER)
.map((value) => value.trim())
.filter((value) => Boolean(value))
.forEach((value) => taxonomyNodes.add(value));
});
}
}
return Array.from(taxonomyNodes.values());
};
//# sourceMappingURL=DSL_DataSpace_PureProtocolProcessorPlugin.js.map