diff --git a/.changeset/big-pens-return.md b/.changeset/big-pens-return.md new file mode 100644 index 0000000000..f1c63a8114 --- /dev/null +++ b/.changeset/big-pens-return.md @@ -0,0 +1,5 @@ +--- +"@finos/legend-graph": patch +--- + +**BREAKING CHANGE:** Pass Plugins as a parameter for `V1_getExtraElementProtocolSerializers` and `V1_getExtraElementProtocolDeserializers` diff --git a/.changeset/heavy-carpets-pull.md b/.changeset/heavy-carpets-pull.md new file mode 100644 index 0000000000..ed179efb84 --- /dev/null +++ b/.changeset/heavy-carpets-pull.md @@ -0,0 +1,5 @@ +--- +"@finos/legend-extension-external-store-service": minor +--- + +Add graph support for `Service Store` diff --git a/.changeset/light-nails-battle.md b/.changeset/light-nails-battle.md new file mode 100644 index 0000000000..3dbc0ea621 --- /dev/null +++ b/.changeset/light-nails-battle.md @@ -0,0 +1,5 @@ +--- +"@finos/legend-graph": minor +--- + +Add extension mechanism for `class mapping` diff --git a/.changeset/loud-foxes-deliver.md b/.changeset/loud-foxes-deliver.md new file mode 100644 index 0000000000..ffcc4a24ce --- /dev/null +++ b/.changeset/loud-foxes-deliver.md @@ -0,0 +1,9 @@ +--- +'@finos/legend-extension-dsl-serializer': patch +'@finos/legend-extension-dsl-data-space': patch +'@finos/legend-extension-dsl-diagram': patch +'@finos/legend-extension-dsl-text': patch +'@finos/legend-studio-app': patch +'@finos/legend-query-app': patch +'@finos/legend-manual-tests': patch +--- diff --git a/.changeset/poor-bananas-relate.md b/.changeset/poor-bananas-relate.md new file mode 100644 index 0000000000..586ed0a440 --- /dev/null +++ b/.changeset/poor-bananas-relate.md @@ -0,0 +1,5 @@ +--- +"@finos/legend-studio": minor +--- + +Add extension mechanism for `class mapping` in form mode diff --git a/.changeset/rich-comics-enjoy.md b/.changeset/rich-comics-enjoy.md new file mode 100644 index 0000000000..a42324ff05 --- /dev/null +++ b/.changeset/rich-comics-enjoy.md @@ -0,0 +1,5 @@ +--- +"@finos/legend-graph": patch +--- + +**BREAKING CHANGE:** Removal of old `Service store` specification diff --git a/packages/legend-extension-dsl-data-space/src/models/protocols/pure/DSLDataSpace_PureProtocolProcessorPlugin.ts b/packages/legend-extension-dsl-data-space/src/models/protocols/pure/DSLDataSpace_PureProtocolProcessorPlugin.ts index 94fbff010b..ddba4f3684 100644 --- a/packages/legend-extension-dsl-data-space/src/models/protocols/pure/DSLDataSpace_PureProtocolProcessorPlugin.ts +++ b/packages/legend-extension-dsl-data-space/src/models/protocols/pure/DSLDataSpace_PureProtocolProcessorPlugin.ts @@ -216,6 +216,7 @@ export class DSLDataSpace_PureProtocolProcessorPlugin extends PureProtocolProces return [ ( elementProtocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], ): PlainObject | undefined => { if (elementProtocol instanceof V1_DataSpace) { return serialize(V1_dataSpaceModelSchema, elementProtocol); @@ -229,6 +230,7 @@ export class DSLDataSpace_PureProtocolProcessorPlugin extends PureProtocolProces return [ ( json: PlainObject, + plugins: PureProtocolProcessorPlugin[], ): V1_PackageableElement | undefined => { if (json._type === V1_DATA_SPACE_ELEMENT_PROTOCOL_TYPE) { return deserialize(V1_dataSpaceModelSchema, json); diff --git a/packages/legend-extension-dsl-diagram/src/models/protocols/pure/DSLDiagram_PureProtocolProcessorPlugin.ts b/packages/legend-extension-dsl-diagram/src/models/protocols/pure/DSLDiagram_PureProtocolProcessorPlugin.ts index 1614766dcf..1afc8b319d 100644 --- a/packages/legend-extension-dsl-diagram/src/models/protocols/pure/DSLDiagram_PureProtocolProcessorPlugin.ts +++ b/packages/legend-extension-dsl-diagram/src/models/protocols/pure/DSLDiagram_PureProtocolProcessorPlugin.ts @@ -127,6 +127,7 @@ export class DSLDiagram_PureProtocolProcessorPlugin extends PureProtocolProcesso return [ ( elementProtocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], ): PlainObject | undefined => { if (elementProtocol instanceof V1_Diagram) { return serialize(V1_diagramModelSchema, elementProtocol); @@ -140,6 +141,7 @@ export class DSLDiagram_PureProtocolProcessorPlugin extends PureProtocolProcesso return [ ( json: PlainObject, + plugins: PureProtocolProcessorPlugin[], ): V1_PackageableElement | undefined => { if (json._type === V1_DIAGRAM_ELEMENT_PROTOCOL_TYPE) { return deserialize(V1_diagramModelSchema, json); diff --git a/packages/legend-extension-dsl-serializer/src/index.ts b/packages/legend-extension-dsl-serializer/src/index.ts index fbf3c467d9..3d0c803bb3 100644 --- a/packages/legend-extension-dsl-serializer/src/index.ts +++ b/packages/legend-extension-dsl-serializer/src/index.ts @@ -15,3 +15,5 @@ */ export * from './DSLSerializer_Extension'; +export * from './models/metamodels/pure/model/packageableElements/store/Binding'; +export { getBinding } from './graphManager/DSLSerializer_GraphManagerHelper'; diff --git a/packages/legend-extension-dsl-serializer/src/models/protocols/pure/DSLSerializer_PureProtocolProcessorPlugin.ts b/packages/legend-extension-dsl-serializer/src/models/protocols/pure/DSLSerializer_PureProtocolProcessorPlugin.ts index 060d84882c..74c903b5dd 100644 --- a/packages/legend-extension-dsl-serializer/src/models/protocols/pure/DSLSerializer_PureProtocolProcessorPlugin.ts +++ b/packages/legend-extension-dsl-serializer/src/models/protocols/pure/DSLSerializer_PureProtocolProcessorPlugin.ts @@ -224,6 +224,7 @@ export class DSLSerializer_PureProtocolProcessorPlugin return [ ( elementProtocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], ): PlainObject | undefined => { if (elementProtocol instanceof V1_Binding) { return serialize(V1_bindingModelSchema, elementProtocol); @@ -239,6 +240,7 @@ export class DSLSerializer_PureProtocolProcessorPlugin return [ ( json: PlainObject, + plugins: PureProtocolProcessorPlugin[], ): V1_PackageableElement | undefined => { if (json._type === V1_BINDING_ELEMENT_PROTOCOL_TYPE) { return deserialize(V1_bindingModelSchema, json); diff --git a/packages/legend-extension-dsl-text/src/models/protocols/pure/DSLText_PureProtocolProcessorPlugin.ts b/packages/legend-extension-dsl-text/src/models/protocols/pure/DSLText_PureProtocolProcessorPlugin.ts index 9c3d403dd8..cd324837e5 100644 --- a/packages/legend-extension-dsl-text/src/models/protocols/pure/DSLText_PureProtocolProcessorPlugin.ts +++ b/packages/legend-extension-dsl-text/src/models/protocols/pure/DSLText_PureProtocolProcessorPlugin.ts @@ -115,6 +115,7 @@ export class DSLText_PureProtocolProcessorPlugin extends PureProtocolProcessorPl return [ ( elementProtocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], ): PlainObject | undefined => { if (elementProtocol instanceof V1_Text) { return serialize(V1_textModelSchema, elementProtocol); @@ -128,6 +129,7 @@ export class DSLText_PureProtocolProcessorPlugin extends PureProtocolProcessorPl return [ ( json: PlainObject, + plugins: PureProtocolProcessorPlugin[], ): V1_PackageableElement | undefined => { if (json._type === V1_TEXT_ELEMENT_PROTOCOL_TYPE) { return deserialize(V1_textModelSchema, json); diff --git a/packages/legend-extension-external-store-service/.npmignore b/packages/legend-extension-external-store-service/.npmignore new file mode 100644 index 0000000000..9fff3807c4 --- /dev/null +++ b/packages/legend-extension-external-store-service/.npmignore @@ -0,0 +1,7 @@ +/build +/style +**/__mocks__/** +**/__tests__/** +/*.* +!tsconfig.json +!tsconfig.package.json diff --git a/packages/legend-extension-external-store-service/README.md b/packages/legend-extension-external-store-service/README.md new file mode 100644 index 0000000000..dce40cdfef --- /dev/null +++ b/packages/legend-extension-external-store-service/README.md @@ -0,0 +1,3 @@ +# @finos/legend-extension-external-store-service + +Legend Studio extension for `Service Store` diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_ServiceStoreTransformer.ts b/packages/legend-extension-external-store-service/_package.config.js similarity index 52% rename from packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_ServiceStoreTransformer.ts rename to packages/legend-extension-external-store-service/_package.config.js index 0b1f80c0c8..cc9ec5d80e 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_ServiceStoreTransformer.ts +++ b/packages/legend-extension-external-store-service/_package.config.js @@ -14,15 +14,20 @@ * limitations under the License. */ -import type { ServiceStore } from '../../../../../../metamodels/pure/packageableElements/store/relational/model/ServiceStore'; -import { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; -import { V1_initPackageableElement } from './V1_CoreTransformerHelper'; +import { generateBundleCopyrightText } from '../../scripts/copyright/PackageCopyrightHelper.js'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; -export const V1_transformServiceStore = ( - element: ServiceStore, -): V1_ServiceStore => { - const serviceStore = new V1_ServiceStore(); - V1_initPackageableElement(serviceStore, element); - serviceStore.docLink = element.docLink; - return serviceStore; +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default { + publish: { + typescript: { + main: './tsconfig.build.json', + others: ['./tsconfig.package.json'], + }, + }, + build: { + copyrightText: generateBundleCopyrightText(__dirname), + }, }; diff --git a/packages/legend-extension-external-store-service/jest.config.js b/packages/legend-extension-external-store-service/jest.config.js new file mode 100644 index 0000000000..d64ff02e78 --- /dev/null +++ b/packages/legend-extension-external-store-service/jest.config.js @@ -0,0 +1,39 @@ +/** + * 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 base from '../../scripts/jest/jest.config.base.js'; +import { loadJSON } from '@finos/legend-dev-utils/DevUtils'; + +const packageJson = loadJSON('./package.json'); + +export default { + ...base, + displayName: packageJson.name, + name: packageJson.name, + rootDir: '../..', + testEnvironment: 'jsdom', + setupFiles: [ + ...base.setupFiles, + '/scripts/jest/setupTests/setupPolyfills.js', + ], + moduleNameMapper: { + ...base.moduleNameMapper, + '^monaco-editor$': '@finos/legend-art/lib/testMocks/MockedMonacoEditor.js', + }, + testMatch: [ + '/packages/legend-extension-external-store-service/src/**/__tests__/**/*(*.)test.[jt]s?(x)', + ], +}; diff --git a/packages/legend-extension-external-store-service/package.json b/packages/legend-extension-external-store-service/package.json new file mode 100644 index 0000000000..7e64c91dc2 --- /dev/null +++ b/packages/legend-extension-external-store-service/package.json @@ -0,0 +1,77 @@ +{ + "name": "@finos/legend-extension-external-store-service", + "version": "0.0.0", + "description": "Legend extension for Service Store", + "keywords": [ + "legend", + "legend-extension", + "extension", + "store", + "external-store", + "service-store" + ], + "homepage": "https://github.com/finos/legend-studio/tree/master/packages/legend-extension-external-store-service", + "bugs": { + "url": "https://github.com/finos/legend-studio/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/finos/legend-studio.git", + "directory": "packages/legend-extension-external-store-service" + }, + "license": "Apache-2.0", + "sideEffects": false, + "type": "module", + "main": "lib/index.js", + "module": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build": "yarn clean && yarn build:tsc", + "build:tsc": "tsc --project ./tsconfig.build.json", + "clean": "rimraf \"lib\" \"build\"", + "dev": "yarn dev:tsc", + "dev:tsc": "tsc --watch --preserveWatchOutput", + "lint:js": "cross-env NODE_ENV=production eslint --cache --cache-location ./build/.eslintcache --report-unused-disable-directives --parser-options=project:\"./tsconfig.json\" \"./src/**/*.{js,ts,tsx}\"", + "publish:prepare": "node ../../scripts/release/preparePublishContent.js", + "test": "jest", + "test:watch": "jest --watch" + }, + "dependencies": { + "@finos/legend-art": "workspace:*", + "@finos/legend-extension-dsl-serializer": "workspace:*", + "@finos/legend-graph": "workspace:*", + "@finos/legend-model-storage": "workspace:*", + "@finos/legend-shared": "workspace:*", + "@finos/legend-studio": "workspace:*", + "@types/react": "17.0.32", + "mobx": "6.3.5", + "mobx-react-lite": "3.2.1", + "monaco-editor": "0.29.1", + "react": "17.0.2", + "serializr": "2.0.5" + }, + "devDependencies": { + "@finos/legend-dev-utils": "workspace:*", + "cross-env": "7.0.3", + "eslint": "8.1.0", + "jest": "27.3.1", + "npm-run-all": "4.1.5", + "rimraf": "3.0.2", + "sass": "1.43.3", + "typescript": "4.4.4" + }, + "peerDependencies": { + "react": "^17.0.0" + }, + "publishConfig": { + "directory": "build/publishContent" + }, + "extensions": { + "graphPreset": "@finos/legend-graph-preset-external-store-service", + "pureProtocolProcessorPlugin": "@finos/legend-graph-plugin-external-store-service-pure-protocol-processor", + "pureGraphManagerPlugin": "@finos/legend-graph-plugin-external-store-service-pure-graph-manager", + "pureGraphPlugin": "@finos/legend-graph-plugin-external-store-service-pure-graph", + "studioPreset": "@finos/legend-studio-preset-external-store-service", + "studioPlugin": "@finos/legend-studio-plugin-external-store-service" + } +} diff --git a/packages/legend-extension-external-store-service/src/ESService_Extension.ts b/packages/legend-extension-external-store-service/src/ESService_Extension.ts new file mode 100644 index 0000000000..1da3941bf5 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/ESService_Extension.ts @@ -0,0 +1,49 @@ +/** + * 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'; +import type { GraphPluginManager } from '@finos/legend-graph'; +import { AbstractPreset } from '@finos/legend-shared'; +import { ESService_PureGraphManagerPlugin } from './graphManager/ESService_PureGraphManagerPlugin'; +import { ESService_PureProtocolProcessorPlugin } from './models/protocols/pure/ESService_PureProtocolProcessorPlugin'; +import type { StudioPluginManager } from '@finos/legend-studio'; +import { ESService_PureGraphPlugin } from './graph/ESService_PureGraphPlugin'; +import { ESService_StudioPlugin } from './components/ESService_StudioPlugin'; + +export class ESService_GraphPreset extends AbstractPreset { + constructor() { + super(packageJson.extensions.graphPreset, packageJson.version); + } + + install(pluginManager: GraphPluginManager): void { + new ESService_PureGraphPlugin().install(pluginManager); + new ESService_PureGraphManagerPlugin().install(pluginManager); + new ESService_PureProtocolProcessorPlugin().install(pluginManager); + } +} + +export class ESService_StudioPreset extends AbstractPreset { + constructor() { + super(packageJson.extensions.studioPreset, packageJson.version); + } + + install(pluginManager: StudioPluginManager): void { + new ESService_StudioPlugin().install(pluginManager); + new ESService_PureGraphPlugin().install(pluginManager); + new ESService_PureGraphManagerPlugin().install(pluginManager); + new ESService_PureProtocolProcessorPlugin().install(pluginManager); + } +} diff --git a/packages/legend-extension-external-store-service/src/components/ESService_StudioPlugin.tsx b/packages/legend-extension-external-store-service/src/components/ESService_StudioPlugin.tsx new file mode 100644 index 0000000000..86b6e04aa8 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/components/ESService_StudioPlugin.tsx @@ -0,0 +1,164 @@ +/** + * 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'; +import { + StudioPlugin, + UnsupportedElementEditorState, + UnsupportedInstanceSetImplementationState, +} from '@finos/legend-studio'; +import type { + StudioPluginManager, + NewElementFromStateCreator, + EditorStore, + ElementEditorState, + ElementEditorStateCreator, + ElementTypeGetter, + ElementProjectExplorerDnDTypeGetter, + NewElementState, + DSLMapping_StudioPlugin_Extension, + SetImplemtationClassifier, + MappingElementStateCreator, + MappingElement, + MappingElementState, + MappingElementSourceGetter, + MappingElementSource, +} from '@finos/legend-studio'; +import type { + PackageableElement, + SetImplementation, +} from '@finos/legend-graph'; +import { ServiceStore } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; +import { RootServiceInstanceSetImplementation } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/RootServiceInstanceSetImplementation'; + +const SERVICE_STORE_ELEMENT_TYPE = 'SERVICE_STORE'; +const SERVICE_STORE_ELEMENT_PROJECT_EXPLORER_DND_TYPE = + 'PROJECT_EXPLORER_SERVICE_STORE'; +const SERVICE_STORE_MAPPING_TYPE = 'serviceStore'; + +export class ESService_StudioPlugin + extends StudioPlugin + implements DSLMapping_StudioPlugin_Extension +{ + constructor() { + super(packageJson.extensions.studioPlugin, packageJson.version); + } + + install(pluginManager: StudioPluginManager): void { + pluginManager.registerStudioPlugin(this); + } + + getExtraSupportedElementTypes(): string[] { + return [SERVICE_STORE_ELEMENT_TYPE]; + } + + getExtraElementTypeGetters(): ElementTypeGetter[] { + return [ + (element: PackageableElement): string | undefined => { + if (element instanceof ServiceStore) { + return SERVICE_STORE_ELEMENT_TYPE; + } + return undefined; + }, + ]; + } + + getExtraNewElementFromStateCreators(): NewElementFromStateCreator[] { + return [ + ( + type: string, + name: string, + state: NewElementState, + ): PackageableElement | undefined => { + if (type === SERVICE_STORE_ELEMENT_TYPE) { + return new ServiceStore(name); + } + return undefined; + }, + ]; + } + + getExtraElementEditorStateCreators(): ElementEditorStateCreator[] { + return [ + ( + editorStore: EditorStore, + element: PackageableElement, + ): ElementEditorState | undefined => { + if (element instanceof ServiceStore) { + return new UnsupportedElementEditorState(editorStore, element); + } + return undefined; + }, + ]; + } + + getExtraElementProjectExplorerDnDTypeGetters(): ElementProjectExplorerDnDTypeGetter[] { + return [ + (element: PackageableElement): string | undefined => { + if (element instanceof ServiceStore) { + return SERVICE_STORE_ELEMENT_PROJECT_EXPLORER_DND_TYPE; + } + return undefined; + }, + ]; + } + + getExtraGrammarTextEditorDnDTypes(): string[] { + return [SERVICE_STORE_ELEMENT_PROJECT_EXPLORER_DND_TYPE]; + } + + getExtraSetImplementationClassifiers(): SetImplemtationClassifier[] { + return [ + (setImplementation: SetImplementation): string | undefined => { + if (setImplementation instanceof RootServiceInstanceSetImplementation) { + return SERVICE_STORE_MAPPING_TYPE; + } + return undefined; + }, + ]; + } + + getExtraMappingElementStateCreators(): MappingElementStateCreator[] { + return [ + ( + mappingElement: MappingElement | undefined, + editorStore: EditorStore, + ): MappingElementState | undefined => { + if ( + mappingElement !== undefined && + mappingElement instanceof RootServiceInstanceSetImplementation + ) { + return new UnsupportedInstanceSetImplementationState( + editorStore, + mappingElement, + ); + } + return undefined; + }, + ]; + } + + getExtraMappingElementSourceGetters(): MappingElementSourceGetter[] { + return [ + (mappingElement: MappingElement): MappingElementSource | undefined => { + if (mappingElement instanceof RootServiceInstanceSetImplementation) { + return mappingElement.class.value; + } + return undefined; + }, + ]; + } +} diff --git a/packages/legend-extension-external-store-service/src/graph/ESService_PureGraphPlugin.ts b/packages/legend-extension-external-store-service/src/graph/ESService_PureGraphPlugin.ts new file mode 100644 index 0000000000..82429cda73 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/graph/ESService_PureGraphPlugin.ts @@ -0,0 +1,38 @@ +/** + * 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'; +import { ServiceStore } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; +import type { Clazz } from '@finos/legend-shared'; +import type { + GraphPluginManager, + PackageableElement, +} from '@finos/legend-graph'; +import { PureGraphPlugin } from '@finos/legend-graph'; + +export class ESService_PureGraphPlugin extends PureGraphPlugin { + constructor() { + super(packageJson.extensions.pureGraphPlugin, packageJson.version); + } + + install(pluginManager: GraphPluginManager): void { + pluginManager.registerPureGraphPlugin(this); + } + + override getExtraPureGraphExtensionClasses(): Clazz[] { + return [ServiceStore]; + } +} diff --git a/packages/legend-extension-external-store-service/src/graphManager/ESService_GraphManagerHelper.ts b/packages/legend-extension-external-store-service/src/graphManager/ESService_GraphManagerHelper.ts new file mode 100644 index 0000000000..fe6aa92889 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/graphManager/ESService_GraphManagerHelper.ts @@ -0,0 +1,26 @@ +/** + * 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 type { PureModel } from '@finos/legend-graph'; +import { guaranteeType } from '@finos/legend-shared'; +import { ServiceStore } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; + +export const getServiceStore = (path: string, graph: PureModel): ServiceStore => + guaranteeType( + graph.getStore(path), + ServiceStore, + `Can't find service store '${path}'`, + ); diff --git a/packages/legend-extension-external-store-service/src/graphManager/ESService_PureGraphManagerPlugin.ts b/packages/legend-extension-external-store-service/src/graphManager/ESService_PureGraphManagerPlugin.ts new file mode 100644 index 0000000000..93d33af040 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/graphManager/ESService_PureGraphManagerPlugin.ts @@ -0,0 +1,73 @@ +/** + * 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'; +import { ServiceStore } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; +import type { + DSLMapping_PureGraphManagerPlugin_Extension, + GraphPluginManager, + PackageableElement, + PureGrammarElementLabeler, + PureGrammarConnectionLabeler, +} from '@finos/legend-graph'; +import { PureGraphManagerPlugin } from '@finos/legend-graph'; +import { ServiceStoreConnection } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/connection/ServiceStoreConnection'; + +const PURE_GRAMMAR_SERVICE_STORE_PARSER_NAME = 'ServiceStore'; +const PURE_GRAMMAR_SERVICE_STORE_ELEMENT_TYPE_LABEL = 'ServiceStore'; +const PURE_GRAMMAR_SERVICE_STORE_CONNECTION_TYPE_LABEL = + 'ServiceStoreConnection'; + +export class ESService_PureGraphManagerPlugin + extends PureGraphManagerPlugin + implements DSLMapping_PureGraphManagerPlugin_Extension +{ + constructor() { + super(packageJson.extensions.pureGraphManagerPlugin, packageJson.version); + } + + install(pluginManager: GraphPluginManager): void { + pluginManager.registerPureGraphManagerPlugin(this); + } + + override getExtraPureGrammarParserNames(): string[] { + return [PURE_GRAMMAR_SERVICE_STORE_PARSER_NAME]; + } + + override getExtraPureGrammarKeywords(): string[] { + return [PURE_GRAMMAR_SERVICE_STORE_ELEMENT_TYPE_LABEL]; + } + override getExtraPureGrammarElementLabelers(): PureGrammarElementLabeler[] { + return [ + (element: PackageableElement): string | undefined => { + if (element instanceof ServiceStore) { + return PURE_GRAMMAR_SERVICE_STORE_ELEMENT_TYPE_LABEL; + } + return undefined; + }, + ]; + } + getExtraPureGrammarConnectionLabelers(): PureGrammarConnectionLabeler[] { + return [ + (connection): string | undefined => { + if (connection instanceof ServiceStoreConnection) { + return PURE_GRAMMAR_SERVICE_STORE_CONNECTION_TYPE_LABEL; + } + return undefined; + }, + ]; + } +} diff --git a/packages/legend-extension-external-store-service/src/helpers/ESService_Helper.ts b/packages/legend-extension-external-store-service/src/helpers/ESService_Helper.ts new file mode 100644 index 0000000000..11bed3b5cb --- /dev/null +++ b/packages/legend-extension-external-store-service/src/helpers/ESService_Helper.ts @@ -0,0 +1,51 @@ +/** + * 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 { guaranteeType } from '@finos/legend-shared'; +import { ServiceGroup } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup'; +import { ServiceParameter } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter'; +import type { ServiceStoreElement } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement'; +import { ServiceStoreService } from '../models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService'; + +export const getParameter = ( + value: string, + parameters: ServiceParameter[], +): ServiceParameter => + guaranteeType( + parameters.find((parameter: ServiceParameter) => parameter.name === value), + ServiceParameter, + `Can't find service parameter '${value}'`, + ); + +export const getServiceStoreService = ( + elements: ServiceStoreElement[], + value: string, +): ServiceStoreService => + guaranteeType( + elements.find((element) => element.id === value), + ServiceStoreService, + `Can't find service '${value}'`, + ); + +export const getServiceGroup = ( + elements: ServiceStoreElement[], + value: string, +): ServiceGroup => + guaranteeType( + elements.find((element) => element.id === value), + ServiceGroup, + `Can't find service group '${value}'`, + ); diff --git a/packages/legend-extension-external-store-service/src/index.ts b/packages/legend-extension-external-store-service/src/index.ts new file mode 100644 index 0000000000..6e5df16c10 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/index.ts @@ -0,0 +1,18 @@ +/** + * 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. + */ + +export * from './ESService_Extension'; +export * from './models/protocols/pure/ExternalStoreService_PureProtocolPlugin_Extension'; diff --git a/packages/legend-extension-external-store-service/src/models/ESService_ModelUtils.ts b/packages/legend-extension-external-store-service/src/models/ESService_ModelUtils.ts new file mode 100644 index 0000000000..be1f76f9ae --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/ESService_ModelUtils.ts @@ -0,0 +1,43 @@ +/** + * 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. + */ + +export enum SERVICE_STORE_HASH_STRUCTURE { + //ServiceStoreService Store + SERVICE_STORE = 'SERVICE_STORE', + SERVICE_STORE_SERVICE = 'SERVICE_STORE_SERVICE', + SERVICE_GROUP = 'SERVICE_GROUP', + SERVICE_PARAMETER = 'SERVICE_PARAMETER', + SERIALIZATION_FORMAT = 'SERIALIZATION_FORMAT', + SERVICE_GROUP_PTR = 'SERVICE_GROUP_PTR', + SERVICE_STORE_SERVICE_PTR = 'SERVICE_STORE_SERVICE_PTR', + + //Type Reference + COMPLEX_TYPE_REFERENCE = 'COMPLEX_TYPE_REFERENCE', + BOOLEAN_TYPE_REFERENCE = 'BOOLEAN_TYPE_REFERENCE', + FLOAT_TYPE_REFERENCE = 'FLOAT_TYPE_REFERENCE', + INTEGER_TYPE_REFERENCE = 'INTEGER_TYPE_REFERENCE', + STRING_TYPE_REFERENCE = 'STRING_TYPE_REFERENCE', + + //Mapping + LOCAL_MAPPING_PROPERTY = 'LOCAL_MAPPING_PROPERTY', + SERVICE_MAPPING = 'SERVICE_MAPPING', + ROOT_SERVICE_STORE_CLASS_MAPPING = 'ROOT_SERVICE_STORE_CLASS_MAPPING', + PROPERTY_INDEXED_PARAMETER_MAPPING = 'PROPERTY_INDEXED_PARAMETR_MAPPING', + PARAMETER_INDEXED_PARAMETER_MAPPING = 'PARAMETER_INDEXED_PARAMETR_MAPPING', + + //Connection + SERVICE_STORE_CONNECTION = 'SERVICE_STORE_CONNECTION', +} diff --git a/packages/legend-extension-external-store-service/src/models/__tests__/ESService_Roundtrip.test.ts b/packages/legend-extension-external-store-service/src/models/__tests__/ESService_Roundtrip.test.ts new file mode 100644 index 0000000000..322412e3e1 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/__tests__/ESService_Roundtrip.test.ts @@ -0,0 +1,37 @@ +/** + * 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 type { Entity } from '@finos/legend-model-storage'; +import { unitTest } from '@finos/legend-shared'; +import { roundtripTestData } from './TEST_DATA__ESService_Roundtrip'; +import { ESService_GraphPreset } from '../../ESService_Extension'; +import { DSLSerializer_GraphPreset } from '@finos/legend-extension-dsl-serializer'; +import { + TEST__GraphPluginManager, + TEST__checkBuildingElementsRoundtrip, +} from '@finos/legend-graph'; + +const pluginManager = new TEST__GraphPluginManager(); +pluginManager + .usePresets([new ESService_GraphPreset(), new DSLSerializer_GraphPreset()]) + .install(); + +test(unitTest('Service store import resolution roundtrip'), async () => { + await TEST__checkBuildingElementsRoundtrip( + roundtripTestData as Entity[], + pluginManager, + ); +}); diff --git a/packages/legend-extension-external-store-service/src/models/__tests__/TEST_DATA__ESService_Roundtrip.ts b/packages/legend-extension-external-store-service/src/models/__tests__/TEST_DATA__ESService_Roundtrip.ts new file mode 100644 index 0000000000..e5a0a51952 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/__tests__/TEST_DATA__ESService_Roundtrip.ts @@ -0,0 +1,290 @@ +/** + * 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. + */ + +export const roundtripTestData = [ + { + path: 'test::A', + content: { + _type: 'class', + name: 'A', + package: 'test', + properties: [ + { + multiplicity: { + lowerBound: 1, + upperBound: 1, + }, + name: 'z', + type: 'String', + }, + ], + }, + classifierPath: 'meta::pure::metamodel::type::Class', + }, + { + path: 'anything::schemaSet1', + content: { + _type: 'externalFormatSchemaSet', + format: 'FlatData', + name: 'schemaSet1', + package: 'anything', + schemas: [ + { + content: 'test content', + id: 'id1', + location: 'location1', + }, + { + content: 'test content2', + id: 'id2', + location: 'location2', + }, + ], + }, + classifierPath: 'meta::external::shared::format::metamodel::SchemaSet', + }, + { + path: 'anything::binding1', + content: { + _type: 'binding', + contentType: 'test', + includedStores: [], + modelUnit: { + packageableElementExcludes: [], + packageableElementIncludes: [], + }, + name: 'binding1', + package: 'anything', + schemaSet: 'schemaSet1', + }, + classifierPath: 'meta::external::shared::format::binding::Binding', + }, + { + path: 'anything::ServiceStore1', + content: { + _type: 'serviceStore', + name: 'ServiceStore1', + package: 'anything', + elements: [ + { + _type: 'service', + id: 'TestService', + method: 'GET', + parameters: [ + { + location: 'QUERY', + name: 'serializationFormat', + serializationFormat: {}, + type: { + _type: 'string', + list: false, + }, + }, + ], + path: '/testService', + response: { + _type: 'complex', + binding: 'anything::binding1', + list: false, + type: 'test::A', + }, + security: [], + }, + ], + includedStores: [], + }, + classifierPath: 'meta::external::store::service::metamodel::ServiceStore', + }, + { + path: 'anything::ServiceStore2', + content: { + _type: 'serviceStore', + name: 'ServiceStore2', + package: 'anything', + elements: [ + { + _type: 'serviceGroup', + elements: [ + { + _type: 'service', + id: 'TestService1', + method: 'GET', + parameters: [ + { + location: 'QUERY', + name: 'param', + serializationFormat: {}, + type: { + _type: 'string', + list: false, + }, + }, + { + location: 'QUERY', + name: 'param2', + serializationFormat: {}, + type: { + _type: 'integer', + list: false, + }, + }, + ], + path: '/testService1', + response: { + _type: 'complex', + binding: 'anything::binding1', + list: false, + type: 'test::A', + }, + security: [], + }, + { + _type: 'service', + id: 'TestService2', + method: 'GET', + parameters: [ + { + location: 'QUERY', + name: 'param1', + serializationFormat: {}, + type: { + _type: 'boolean', + list: false, + }, + }, + ], + path: '/testService2', + response: { + _type: 'complex', + binding: 'anything::binding1', + list: false, + type: 'test::A', + }, + security: [], + }, + ], + id: 'TestServiceGroup', + path: '/testServices', + }, + ], + includedStores: [], + }, + classifierPath: 'meta::external::store::service::metamodel::ServiceStore', + }, + { + path: 'anything::mapping', + content: { + _type: 'mapping', + classMappings: [ + { + _type: 'serviceStore', + class: 'test::A', + localMappingProperties: [], + root: 'true', + servicesMapping: [ + { + parameterMappings: [ + { + _type: 'parameter', + serviceParameter: 'serializationFormat', + transform: { + _type: 'lambda', + body: [ + { + _type: 'string', + multiplicity: { + lowerBound: 1, + upperBound: 1, + }, + values: ['CSV'], + }, + ], + parameters: [], + }, + }, + ], + service: { + service: 'TestService', + serviceStore: 'anything::ServiceStore1', + }, + }, + ], + }, + ], + enumerationMappings: [], + includedMappings: [], + name: 'mapping', + package: 'anything', + tests: [], + }, + classifierPath: 'meta::pure::mapping::Mapping', + }, + { + path: 'anything::tConn', + content: { + _type: 'connection', + name: 'tConn', + package: 'anything', + connectionValue: { + _type: 'serviceStore', + baseUrl: 'test', + element: 'anything::ServiceStore1', + }, + }, + classifierPath: 'meta::pure::runtime::PackageableConnection', + }, + { + path: '__internal__::SectionIndex', + content: { + _type: 'sectionIndex', + name: 'SectionIndex', + package: '__internal__', + sections: [ + { + _type: 'importAware', + imports: [], + elements: ['test::A'], + parserName: 'Pure', + }, + { + _type: 'importAware', + imports: ['anything'], + elements: ['anything::ServiceStore1'], + parserName: 'ServiceStore', + }, + { + _type: 'importAware', + imports: ['anything'], + elements: ['anything::ServiceStore2'], + parserName: 'ServiceStore', + }, + { + _type: 'importAware', + imports: ['anything'], + elements: ['anything::mapping'], + parserName: 'Mapping', + }, + { + _type: 'importAware', + imports: ['anything'], + elements: ['anything::tConn'], + parserName: 'Connection', + }, + ], + }, + classifierPath: 'meta::pure::metamodel::section::SectionIndex', + }, +]; diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/connection/ServiceStoreConnection.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/connection/ServiceStoreConnection.ts new file mode 100644 index 0000000000..7c88f2c023 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/connection/ServiceStoreConnection.ts @@ -0,0 +1,56 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { + ConnectionVisitor, + PackageableElementReference, +} from '@finos/legend-graph'; +import { Connection } from '@finos/legend-graph'; +import { action, computed, makeObservable, observable } from 'mobx'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import type { ServiceStore } from '../model/ServiceStore'; + +export class ServiceStoreConnection extends Connection implements Hashable { + baseUrl!: string; + + constructor(store: PackageableElementReference) { + super(store); + + makeObservable(this, { + baseUrl: observable, + setUrl: action, + hashCode: computed, + }); + } + + setUrl(value: string): void { + this.baseUrl = value; + } + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE_CONNECTION, + this.store.hashValue, + this.baseUrl, + ]); + } + + accept_ConnectionVisitor(visitor: ConnectionVisitor): T { + return visitor.visit_Connection(this); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/LocalMappingProperty.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/LocalMappingProperty.ts new file mode 100644 index 0000000000..a03810f4a2 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/LocalMappingProperty.ts @@ -0,0 +1,60 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { Multiplicity } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; + +export class LocalMappingProperty implements Hashable { + name!: string; + type!: string; + multiplicity!: Multiplicity; + + constructor() { + makeObservable(this, { + name: observable, + type: observable, + multiplicity: observable, + setName: action, + setType: action, + setMultiplicity: action, + hashCode: computed, + }); + } + + setName(value: string): void { + this.name = value; + } + + setType(value: string): void { + this.type = value; + } + + setMultiplicity(value: Multiplicity): void { + this.multiplicity = value; + } + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.LOCAL_MAPPING_PROPERTY, + this.name, + this.type, + this.multiplicity, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ParameterIndexedParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ParameterIndexedParameterMapping.ts new file mode 100644 index 0000000000..fd55592a5e --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ParameterIndexedParameterMapping.ts @@ -0,0 +1,51 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { RawLambda } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import { ServiceParameterMapping } from './ServiceParameterMapping'; +import { action, computed, makeObservable, observable } from 'mobx'; + +export class ParameterIndexedParameterMapping + extends ServiceParameterMapping + implements Hashable +{ + transform!: RawLambda; + + constructor() { + super(); + + makeObservable(this, { + transform: observable, + setTransform: action, + hashCode: computed, + }); + } + + setTransform(value: RawLambda): void { + this.transform = value; + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.PARAMETER_INDEXED_PARAMETER_MAPPING, + this.serviceParameter.name, + this.transform, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/PropertyIndexedParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/PropertyIndexedParameterMapping.ts new file mode 100644 index 0000000000..f1275d382c --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/PropertyIndexedParameterMapping.ts @@ -0,0 +1,50 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import { ServiceParameterMapping } from './ServiceParameterMapping'; +import { action, computed, makeObservable, observable } from 'mobx'; + +export class PropertyIndexedParameterMapping + extends ServiceParameterMapping + implements Hashable +{ + property!: string; + + constructor() { + super(); + + makeObservable(this, { + property: observable, + setProperty: action, + hashCode: computed, + }); + } + + setProperty(value: string): void { + this.property = value; + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.PROPERTY_INDEXED_PARAMETER_MAPPING, + this.serviceParameter.name, + this.property, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/RootServiceInstanceSetImplementation.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/RootServiceInstanceSetImplementation.ts new file mode 100644 index 0000000000..668a48a26f --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/RootServiceInstanceSetImplementation.ts @@ -0,0 +1,112 @@ +/** + * 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, makeObservable, computed } from 'mobx'; +import type { Hashable } from '@finos/legend-shared'; +import { hashArray, addUniqueEntry, deleteEntry } from '@finos/legend-shared'; +import type { + Class, + InferableMappingElementIdValue, + InferableMappingElementRoot, + Mapping, + PackageableElementReference, + PropertyMapping, + SetImplementationVisitor, +} from '@finos/legend-graph'; +import { InstanceSetImplementation } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import type { LocalMappingProperty } from './LocalMappingProperty'; +import type { ServiceMapping } from './ServiceMapping'; + +export class RootServiceInstanceSetImplementation + extends InstanceSetImplementation + implements Hashable +{ + localMappingProperties: LocalMappingProperty[] = []; + servicesMapping: ServiceMapping[] = []; + + constructor( + id: InferableMappingElementIdValue, + parent: Mapping, + _class: PackageableElementReference, + root: InferableMappingElementRoot, + ) { + super(id, parent, _class, root); + + makeObservable(this, { + localMappingProperties: observable, + servicesMapping: observable, + addLocalMappingProperty: action, + deleteLocalMappingProperty: action, + addServiceMapping: action, + deleteServiceMapping: action, + hashCode: computed, + }); + } + + addLocalMappingProperty(value: LocalMappingProperty): void { + addUniqueEntry(this.localMappingProperties, value); + } + + deleteLocalMappingProperty(value: LocalMappingProperty): void { + deleteEntry(this.localMappingProperties, value); + } + + addServiceMapping(value: ServiceMapping): void { + addUniqueEntry(this.servicesMapping, value); + } + + deleteServiceMapping(value: ServiceMapping): void { + deleteEntry(this.servicesMapping, value); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.ROOT_SERVICE_STORE_CLASS_MAPPING, + this.id.valueForSerialization ?? '', + this.class.hashValue, + this.root.valueForSerialization.toString(), + hashArray(this.localMappingProperties), + hashArray(this.servicesMapping), + ]); + } + + accept_SetImplementationVisitor(visitor: SetImplementationVisitor): T { + return visitor.visit_SetImplementation(this); + } + + getEmbeddedSetImplmentations(): InstanceSetImplementation[] { + return []; + } + + findPropertyMapping( + propertyName: string, + targetId: string | undefined, + ): PropertyMapping | undefined { + let properties = undefined; + properties = this.propertyMappings.filter( + (propertyMapping) => propertyMapping.property.value.name === propertyName, + ); + if (targetId === undefined || properties.length === 1) { + return properties[0]; + } + return properties.find( + (propertyMapping) => + propertyMapping.targetSetImplementation && + propertyMapping.targetSetImplementation.id.value === targetId, + ); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceMapping.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceMapping.ts new file mode 100644 index 0000000000..430b9137cd --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceMapping.ts @@ -0,0 +1,60 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { addUniqueEntry, deleteEntry, hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import type { ServiceParameterMapping } from './ServiceParameterMapping'; +import type { ServiceStoreService } from '../model/ServiceStoreService'; +import type { RootServiceInstanceSetImplementation } from './RootServiceInstanceSetImplementation'; + +export class ServiceMapping implements Hashable { + owner!: RootServiceInstanceSetImplementation; + service!: ServiceStoreService; + parameterMappings: ServiceParameterMapping[] = []; + + constructor() { + makeObservable(this, { + service: observable, + parameterMappings: observable, + setService: action, + addServiceMapping: action, + deleteServiceMapping: action, + hashCode: computed, + }); + } + + setService(value: string): void { + this.service.setId(value); + } + + addServiceMapping(value: ServiceParameterMapping): void { + addUniqueEntry(this.parameterMappings, value); + } + + deleteServiceMapping(value: ServiceParameterMapping): void { + deleteEntry(this.parameterMappings, value); + } + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_MAPPING, + this.service.id, + hashArray(this.parameterMappings), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceParameterMapping.ts new file mode 100644 index 0000000000..14d774b14a --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceParameterMapping.ts @@ -0,0 +1,36 @@ +/** + * 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, makeObservable, action } from 'mobx'; +import type { Hashable } from '@finos/legend-shared'; +import type { ServiceParameter } from '../model/ServiceParameter'; + +export abstract class ServiceParameterMapping implements Hashable { + serviceParameter!: ServiceParameter; + + constructor() { + makeObservable(this, { + serviceParameter: observable, + setServiceParameter: action, + }); + } + + setServiceParameter(value: string): void { + this.serviceParameter.setName(value); + } + + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme.ts new file mode 100644 index 0000000000..eca55b95cd --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme.ts @@ -0,0 +1,20 @@ +/** + * 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 type { Hashable } from '@finos/legend-shared'; + +export abstract class SecurityScheme implements Hashable { + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SerializationFormat.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SerializationFormat.ts new file mode 100644 index 0000000000..7c716e12f4 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/SerializationFormat.ts @@ -0,0 +1,51 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; + +export class SerializationFormat implements Hashable { + style?: string | undefined; + explode?: boolean | undefined; + + constructor() { + makeObservable(this, { + style: observable, + explode: observable, + setStyle: action, + setExplode: action, + hashCode: computed, + }); + } + + setStyle(value: string): void { + this.style = value; + } + + setExplode(value: boolean): void { + this.explode = value; + } + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERIALIZATION_FORMAT, + this.style ?? '', + this.explode?.toString() ?? '', + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup.ts new file mode 100644 index 0000000000..2d173d6ac1 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup.ts @@ -0,0 +1,53 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { addUniqueEntry, deleteEntry, hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import { ServiceStoreElement } from './ServiceStoreElement'; + +export class ServiceGroup extends ServiceStoreElement implements Hashable { + elements: ServiceStoreElement[] = []; + + constructor() { + super(); + + makeObservable(this, { + elements: observable, + addElement: action, + deleteElement: action, + hashCode: computed, + }); + } + + addElement(value: ServiceStoreElement): void { + addUniqueEntry(this.elements, value); + } + + deleteElement(value: ServiceStoreElement): void { + deleteEntry(this.elements, value); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_GROUP, + this.id, + this.path, + hashArray(this.elements), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter.ts new file mode 100644 index 0000000000..f03cbfa741 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter.ts @@ -0,0 +1,82 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { SerializationFormat } from './SerializationFormat'; +import type { TypeReference } from './TypeReference'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; + +export enum LOCATION { + PATH = 'PATH', + QUERY = 'QUERY', +} + +export class ServiceParameter implements Hashable { + name!: string; + type!: TypeReference; + location!: LOCATION; + enumeration?: string | undefined; + serializationFormat?: SerializationFormat | undefined; + + constructor() { + makeObservable(this, { + name: observable, + type: observable, + location: observable, + enumeration: observable, + serializationFormat: observable, + setName: action, + setType: action, + setLocation: action, + setEnumeration: action, + setSerializationFormat: action, + hashCode: computed, + }); + } + + setName(value: string): void { + this.name = value; + } + + setType(value: TypeReference): void { + this.type = value; + } + + setLocation(value: LOCATION): void { + this.location = value; + } + + setEnumeration(value: string): void { + this.enumeration = value; + } + + setSerializationFormat(value: SerializationFormat): void { + this.serializationFormat = value; + } + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_PARAMETER, + this.name, + this.type, + this.location, + this.enumeration ?? '', + this.serializationFormat ?? '', + ]); + } +} diff --git a/packages/legend-graph/src/models/metamodels/pure/packageableElements/store/relational/model/ServiceStore.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore.ts similarity index 50% rename from packages/legend-graph/src/models/metamodels/pure/packageableElements/store/relational/model/ServiceStore.ts rename to packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore.ts index 15051b7253..46d3a3e025 100644 --- a/packages/legend-graph/src/models/metamodels/pure/packageableElements/store/relational/model/ServiceStore.ts +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore.ts @@ -14,37 +14,55 @@ * limitations under the License. */ -import { hashArray } from '@finos/legend-shared'; +import { observable, action, makeObservable, override } from 'mobx'; +import { hashArray, addUniqueEntry, deleteEntry } from '@finos/legend-shared'; import type { Hashable } from '@finos/legend-shared'; -import { CORE_HASH_STRUCTURE } from '../../../../../../../MetaModelConst'; -import { observable, makeObservable, override } from 'mobx'; -import { Store } from '../../Store'; -import type { PackageableElementVisitor } from '../../../PackageableElement'; +import type { PackageableElementVisitor } from '@finos/legend-graph'; +import { Store } from '@finos/legend-graph'; +import type { ServiceStoreElement } from './ServiceStoreElement'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; export class ServiceStore extends Store implements Hashable { - docLink!: string; + description?: string | undefined; + elements: ServiceStoreElement[] = []; constructor(name: string) { super(name); makeObservable(this, { - docLink: observable, + description: observable, + elements: observable, + setDescription: action, + addElement: action, + deleteElement: action, _elementHashCode: override, }); } + setDescription(value: string): void { + this.description = value; + } + + addElement(value: ServiceStoreElement): void { + addUniqueEntry(this.elements, value); + } + + deleteElement(value: ServiceStoreElement): void { + deleteEntry(this.elements, value); + } + protected override get _elementHashCode(): string { return hashArray([ - CORE_HASH_STRUCTURE.SERVICE_STORE, + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE, this.path, - hashArray(this.includes.map((include) => include.hashValue)), - this.docLink, + this.description ?? '', + hashArray(this.elements), ]); } accept_PackageableElementVisitor( visitor: PackageableElementVisitor, ): T { - return visitor.visit_ServiceStore(this); + return visitor.visit_PackageableElement(this); } } diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement.ts new file mode 100644 index 0000000000..b199bac4f3 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement.ts @@ -0,0 +1,47 @@ +/** + * 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, makeObservable, action } from 'mobx'; +import type { Hashable } from '@finos/legend-shared'; +import type { ServiceStore } from './ServiceStore'; +import type { ServiceGroup } from './ServiceGroup'; + +export abstract class ServiceStoreElement implements Hashable { + private readonly _$nominalTypeBrand!: 'ServiceStoreElement'; + owner!: ServiceStore; + parent?: ServiceGroup | undefined; + id!: string; + path!: string; + + constructor() { + makeObservable(this, { + id: observable, + path: observable, + setId: action, + setPath: action, + }); + } + + setId(value: string): void { + this.id = value; + } + + setPath(value: string): void { + this.path = value; + } + + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService.ts new file mode 100644 index 0000000000..fd07b05191 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService.ts @@ -0,0 +1,101 @@ +/** + * 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, computed, makeObservable, action } from 'mobx'; +import { addUniqueEntry, deleteEntry, hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import { ServiceStoreElement } from './ServiceStoreElement'; +import type { ServiceParameter } from './ServiceParameter'; +import type { SecurityScheme } from './SecurityScheme'; +import type { TypeReference, ComplexTypeReference } from './TypeReference'; + +export enum HTTP_METHOD { + GET = 'GET', + POST = 'POST', +} + +export class ServiceStoreService + extends ServiceStoreElement + implements Hashable +{ + requestBody?: TypeReference | undefined; + method!: HTTP_METHOD; + parameters: ServiceParameter[] = []; + response!: ComplexTypeReference; + security: SecurityScheme[] = []; + + constructor() { + super(); + + makeObservable(this, { + requestBody: observable, + method: observable, + parameters: observable, + response: observable, + security: observable, + setRequestBody: action, + setMethod: action, + addParameter: action, + deleteParameter: action, + setResponse: action, + addSecurity: action, + deleteSecurity: action, + hashCode: computed, + }); + } + + setRequestBody(value: TypeReference): void { + this.requestBody = value; + } + + setMethod(value: HTTP_METHOD): void { + this.method = value; + } + + addParameter(value: ServiceParameter): void { + addUniqueEntry(this.parameters, value); + } + + deleteParameter(value: ServiceParameter): void { + deleteEntry(this.parameters, value); + } + + setResponse(value: ComplexTypeReference): void { + this.response = value; + } + + addSecurity(value: SecurityScheme): void { + addUniqueEntry(this.security, value); + } + + deleteSecurity(value: SecurityScheme): void { + deleteEntry(this.security, value); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE_SERVICE, + this.id, + this.path, + this.requestBody ?? '', + this.method, + hashArray(this.parameters), + this.response, + hashArray(this.security), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference.ts b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference.ts new file mode 100644 index 0000000000..a0eb7420b0 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference.ts @@ -0,0 +1,132 @@ +/** + * 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, makeObservable, computed } from 'mobx'; +import type { Hashable } from '@finos/legend-shared'; +import { hashArray } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../ESService_ModelUtils'; +import type { Class } from '@finos/legend-graph'; +import type { Binding } from '@finos/legend-extension-dsl-serializer'; + +export abstract class TypeReference implements Hashable { + private readonly _$nominalTypeBrand!: 'TypeReference'; + list!: boolean; + + constructor() { + makeObservable(this, { + list: observable, + setList: action, + }); + } + + setList(value: boolean): void { + this.list = value; + } + + abstract get hashCode(): string; +} + +export class BooleanTypeReference extends TypeReference implements Hashable { + constructor() { + super(); + + makeObservable(this, { + hashCode: computed, + }); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.BOOLEAN_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class ComplexTypeReference extends TypeReference implements Hashable { + type!: Class; + binding!: Binding; + + constructor() { + super(); + + makeObservable(this, { + type: observable, + binding: observable, + hashCode: computed, + }); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.COMPLEX_TYPE_REFERENCE, + this.list.toString(), + this.type.path, + this.binding.path, + ]); + } +} + +export class FloatTypeReference extends TypeReference implements Hashable { + constructor() { + super(); + + makeObservable(this, { + hashCode: computed, + }); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.FLOAT_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class IntegerTypeReference extends TypeReference implements Hashable { + constructor() { + super(); + + makeObservable(this, { + hashCode: computed, + }); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.INTEGER_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class StringTypeReference extends TypeReference implements Hashable { + constructor() { + super(); + + makeObservable(this, { + hashCode: computed, + }); + } + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.STRING_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/ESService_PureProtocolProcessorPlugin.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/ESService_PureProtocolProcessorPlugin.ts new file mode 100644 index 0000000000..e470ace72e --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/ESService_PureProtocolProcessorPlugin.ts @@ -0,0 +1,494 @@ +/** + * 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'; +import { V1_ServiceStore } from './v1/model/packageableElements/store/serviceStore/model/V1_ServiceStore'; +import type { PlainObject } from '@finos/legend-shared'; +import { + assertNonEmptyString, + assertNonNullable, + assertType, + guaranteeNonNullable, +} from '@finos/legend-shared'; +import { deserialize, serialize } from 'serializr'; +import { + V1_serviceStoreModelSchema, + V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE, + V1_rootServiceStoreClassMappingModelSchema, + V1_SERVICE_STORE_MAPPING_PROTOCOL_TYPE, + V1_serviceStoreConnectionModelSchema, + V1_SERVICE_STORE_CONNECTION_PROTOCOL_TYPE, +} from './v1/transformation/pureProtocol/V1_ESService_ProtocolHelper'; +import { getServiceStore } from '../../../graphManager/ESService_GraphManagerHelper'; +import { ServiceStore } from '../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; +import type { + GraphPluginManager, + PackageableElement, + V1_ElementProtocolClassifierPathGetter, + V1_ElementProtocolDeserializer, + V1_ElementProtocolSerializer, + V1_ElementTransformer, + V1_GraphBuilderContext, + V1_GraphTransformerContext, + V1_PackageableElement, + V1_ClassMapping, + V1_ClassMappingFirstPassBuilder, + V1_ClassMappingSecondPassBuilder, + V1_ClassMappingTransformer, + V1_ClassMappingDeserializer, + V1_ClassMappingSerializer, + Mapping, + InstanceSetImplementation, + Connection, + PackageableElementReference, + Store, + V1_Connection, + V1_ConnectionBuilder, + V1_ConnectionProtocolDeserializer, + V1_ConnectionProtocolSerializer, + V1_ConnectionTransformer, + DSLMapping_PureProtocolProcessorPlugin_Extension, +} from '@finos/legend-graph'; +import { + PureProtocolProcessorPlugin, + fromElementPathToMappingElementId, + getClassMappingById, + InferableMappingElementIdImplicitValue, + InferableMappingElementRootExplicitValue, + Multiplicity, + V1_ElementBuilder, + V1_initPackageableElement, + V1_transformElementReference, +} from '@finos/legend-graph'; +import { V1_RootServiceStoreClassMapping } from './v1/model/packageableElements/store/serviceStore/mapping/V1_RootServiceStoreClassMapping'; +import { RootServiceInstanceSetImplementation } from '../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/RootServiceInstanceSetImplementation'; +import { LocalMappingProperty } from '../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/LocalMappingProperty'; +import { ServiceMapping } from '../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceMapping'; +import { V1_ServiceStoreConnection } from './v1/model/packageableElements/store/serviceStore/connection/V1_ServicestoreConnection'; +import { + V1_buildServiceParameterMapping, + V1_buildServiceStoreElement, + V1_resolveService, + V1_resolveServiceStore, +} from './v1/transformation/pureGraph/V1_ESService_GraphBuilderHelper'; +import { ServiceStoreConnection } from '../../metamodels/pure/model/packageableElements/store/serviceStore/connection/ServiceStoreConnection'; +import { V1_ServiceMapping } from './v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceMapping'; +import { + V1_transformServiceParameterMapping, + V1_transformServiceStoreElement, + V1_transformServiceToServicePtr, +} from './v1/transformation/pureGraph/V1_ESService_TransformerHelper'; + +const SERVICE_STORE_ELEMENT_CLASSIFIER_PATH = + 'meta::external::store::service::metamodel::ServiceStore'; + +export class ESService_PureProtocolProcessorPlugin + extends PureProtocolProcessorPlugin + implements DSLMapping_PureProtocolProcessorPlugin_Extension +{ + constructor() { + super( + packageJson.extensions.pureProtocolProcessorPlugin, + packageJson.version, + ); + } + + install(pluginManager: GraphPluginManager): void { + pluginManager.registerPureProtocolProcessorPlugin(this); + } + + override V1_getExtraElementBuilders(): V1_ElementBuilder[] { + return [ + new V1_ElementBuilder({ + elementClassName: ServiceStore.name, + _class: V1_ServiceStore, + firstPass: ( + elementProtocol: V1_PackageableElement, + context: V1_GraphBuilderContext, + ): PackageableElement => { + assertType(elementProtocol, V1_ServiceStore); + const element = new ServiceStore(elementProtocol.name); + const path = context.currentSubGraph.buildPath( + elementProtocol.package, + elementProtocol.name, + ); + context.currentSubGraph + .getOrCreatePackage(elementProtocol.package) + .addElement(element); + context.currentSubGraph.setOwnStore(path, element); + return element; + }, + secondPass: ( + elementProtocol: V1_PackageableElement, + context: V1_GraphBuilderContext, + ): void => { + assertType(elementProtocol, V1_ServiceStore); + const path = context.graph.buildPath( + elementProtocol.package, + elementProtocol.name, + ); + const element = getServiceStore(path, context.graph); + element.description = elementProtocol.description; + element.elements = elementProtocol.elements.map( + (serviceStoreElement) => + V1_buildServiceStoreElement( + serviceStoreElement, + element, + context, + ), + ); + }, + }), + ]; + } + + override V1_getExtraElementClassifierPathGetters(): V1_ElementProtocolClassifierPathGetter[] { + return [ + (elementProtocol: V1_PackageableElement): string | undefined => { + if (elementProtocol instanceof V1_ServiceStore) { + return SERVICE_STORE_ELEMENT_CLASSIFIER_PATH; + } + return undefined; + }, + ]; + } + + override V1_getExtraElementProtocolSerializers(): V1_ElementProtocolSerializer[] { + return [ + ( + elementProtocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], + ): PlainObject | undefined => { + if (elementProtocol instanceof V1_ServiceStore) { + return serialize( + V1_serviceStoreModelSchema(plugins), + elementProtocol, + ); + } + return undefined; + }, + ]; + } + + override V1_getExtraElementProtocolDeserializers(): V1_ElementProtocolDeserializer[] { + return [ + ( + json: PlainObject, + plugins: PureProtocolProcessorPlugin[], + ): V1_PackageableElement | undefined => { + if (json._type === V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE) { + return deserialize(V1_serviceStoreModelSchema(plugins), json); + } + return undefined; + }, + ]; + } + + override V1_getExtraElementTransformers(): V1_ElementTransformer[] { + return [ + ( + metamodel: PackageableElement, + context: V1_GraphTransformerContext, + ): V1_PackageableElement | undefined => { + if (metamodel instanceof ServiceStore) { + const protocol = new V1_ServiceStore(); + V1_initPackageableElement(protocol, metamodel); + protocol.name = metamodel.name; + protocol.package = metamodel.package?.fullPath ?? ''; + protocol.description = metamodel.description; + protocol.elements = metamodel.elements.map((element) => + V1_transformServiceStoreElement(element, context), + ); + return protocol; + } + return undefined; + }, + ]; + } + + V1_getExtraClassMappingFirstPassBuilders(): V1_ClassMappingFirstPassBuilder[] { + return [ + ( + classMapping: V1_ClassMapping, + context: V1_GraphBuilderContext, + parent: Mapping, + ): InstanceSetImplementation | undefined => { + if (classMapping instanceof V1_RootServiceStoreClassMapping) { + assertNonEmptyString( + classMapping.class, + `Service store class mapping 'class' is missing`, + ); + assertNonNullable( + classMapping.root, + `Service store class mapping 'root' field is missing`, + ); + const targetClass = context.resolveClass(classMapping.class); + const rootServiceInstanceSetImplementation = + new RootServiceInstanceSetImplementation( + InferableMappingElementIdImplicitValue.create( + classMapping.id ?? + fromElementPathToMappingElementId(targetClass.value.path), + targetClass.value.path, + classMapping.id, + ), + parent, + targetClass, + InferableMappingElementRootExplicitValue.create( + classMapping.root, + ), + ); + rootServiceInstanceSetImplementation.localMappingProperties = + classMapping.localMappingProperties.map((localMappingProperty) => { + const mappingProperty = new LocalMappingProperty(); + mappingProperty.type = localMappingProperty.type; + mappingProperty.name = localMappingProperty.name; + const multiplicity = new Multiplicity( + localMappingProperty.multiplicity.lowerBound, + localMappingProperty.multiplicity.upperBound, + ); + mappingProperty.multiplicity = multiplicity; + return mappingProperty; + }); + rootServiceInstanceSetImplementation.servicesMapping = + classMapping.servicesMapping.map((serviceMapping) => { + const mapping = new ServiceMapping(); + mapping.owner = rootServiceInstanceSetImplementation; + mapping.service = V1_resolveService( + serviceMapping.service, + context, + ); + mapping.parameterMappings = serviceMapping.parameterMappings.map( + (parameter) => { + const parameterMapping = V1_buildServiceParameterMapping( + parameter, + mapping.service, + ); + return parameterMapping; + }, + ); + return mapping; + }); + return rootServiceInstanceSetImplementation; + } + return undefined; + }, + ]; + } + + V1_getExtraClassMappingSecondPassBuilders(): V1_ClassMappingSecondPassBuilder[] { + return [ + ( + classMapping: V1_ClassMapping, + context: V1_GraphBuilderContext, + parent: Mapping, + ): void => { + if (classMapping instanceof V1_RootServiceStoreClassMapping) { + assertNonEmptyString( + classMapping.class, + 'ServiceStore class mapping class is missing', + ); + const id = InferableMappingElementIdImplicitValue.create( + classMapping.id ?? + fromElementPathToMappingElementId( + context.resolveClass(classMapping.class).value.path, + ), + context.resolveClass(classMapping.class).value.path, + classMapping.id, + ).value; + const rootServiceInstanceSetImplementation = getClassMappingById( + parent, + id, + ); + assertType( + rootServiceInstanceSetImplementation, + RootServiceInstanceSetImplementation, + `Class mapping with ID '${id}' is not of type serviceStore set implementation`, + ); + rootServiceInstanceSetImplementation.localMappingProperties = + classMapping.localMappingProperties.map((localMappingProperty) => { + const property = new LocalMappingProperty(); + property.name = localMappingProperty.name; + property.type = localMappingProperty.type; + const multiplicity = new Multiplicity( + localMappingProperty.multiplicity.lowerBound, + localMappingProperty.multiplicity.upperBound, + ); + property.multiplicity = multiplicity; + return property; + }); + rootServiceInstanceSetImplementation.servicesMapping = + classMapping.servicesMapping.map((serviceMapping) => { + const mapping = new ServiceMapping(); + mapping.owner = rootServiceInstanceSetImplementation; + mapping.service = V1_resolveService( + serviceMapping.service, + context, + ); + mapping.parameterMappings = serviceMapping.parameterMappings.map( + (parameter) => { + const parameterMapping = V1_buildServiceParameterMapping( + parameter, + mapping.service, + ); + return parameterMapping; + }, + ); + return mapping; + }); + } + }, + ]; + } + + V1_getExtraClassMappingSerializers(): V1_ClassMappingSerializer[] { + return [ + (value: V1_ClassMapping): V1_ClassMapping | undefined => { + if (value instanceof V1_RootServiceStoreClassMapping) { + return serialize(V1_rootServiceStoreClassMappingModelSchema, value); + } + return undefined; + }, + ]; + } + + V1_getExtraClassMappingDeserializers(): V1_ClassMappingDeserializer[] { + return [ + (json: PlainObject): V1_ClassMapping | undefined => { + if (json._type === V1_SERVICE_STORE_MAPPING_PROTOCOL_TYPE) { + return deserialize(V1_rootServiceStoreClassMappingModelSchema, json); + } + return undefined; + }, + ]; + } + + V1_getExtraClassMappingTransformers(): V1_ClassMappingTransformer[] { + return [ + ( + setImplementation: InstanceSetImplementation, + context: V1_GraphTransformerContext, + ): V1_ClassMapping | undefined => { + if (setImplementation instanceof RootServiceInstanceSetImplementation) { + const classMapping = new V1_RootServiceStoreClassMapping(); + classMapping.class = V1_transformElementReference( + setImplementation.class, + ); + classMapping.id = setImplementation.id.valueForSerialization; + classMapping.root = setImplementation.root.valueForSerialization; + classMapping.localMappingProperties = + setImplementation.localMappingProperties; + classMapping.servicesMapping = setImplementation.servicesMapping.map( + (serviceMapping) => { + const mapping = new V1_ServiceMapping(); + mapping.service = V1_transformServiceToServicePtr( + serviceMapping.service, + ); + mapping.parameterMappings = serviceMapping.parameterMappings.map( + (parameter) => { + const parameterMapping = + V1_transformServiceParameterMapping(parameter); + return parameterMapping; + }, + ); + return mapping; + }, + ); + return classMapping; + } + return undefined; + }, + ]; + } + + V1_getExtraConnectionBuilders(): V1_ConnectionBuilder[] { + return [ + ( + connection: V1_Connection, + context: V1_GraphBuilderContext, + store?: PackageableElementReference | undefined, + ): Connection | undefined => { + if (connection instanceof V1_ServiceStoreConnection) { + const Store = !store + ? V1_resolveServiceStore( + guaranteeNonNullable( + connection.store, + `Service store connection 'store' field is missing`, + ), + context, + ) + : connection.store + ? V1_resolveServiceStore(connection.store, context) + : ((): PackageableElementReference => { + assertType( + store.value, + ServiceStore, + 'ServiceStore connection must have a ServiceStore as its store', + ); + return store as PackageableElementReference; + })(); + const serviceStoreConnection = new ServiceStoreConnection(Store); + serviceStoreConnection.baseUrl = connection.baseUrl; + return serviceStoreConnection; + } + return undefined; + }, + ]; + } + + V1_getExtraConnectionTransformers(): V1_ConnectionTransformer[] { + return [ + ( + metamodel: Connection, + context: V1_GraphTransformerContext, + ): V1_Connection | undefined => { + if (metamodel instanceof ServiceStoreConnection) { + const connection = new V1_ServiceStoreConnection(); + connection.store = V1_transformElementReference(metamodel.store); + connection.baseUrl = metamodel.baseUrl; + return connection; + } + return undefined; + }, + ]; + } + + V1_getExtraConnectionProtocolSerializers(): V1_ConnectionProtocolSerializer[] { + return [ + ( + connectionProtocol: V1_Connection, + ): PlainObject | undefined => { + if (connectionProtocol instanceof V1_ServiceStoreConnection) { + return serialize( + V1_serviceStoreConnectionModelSchema, + connectionProtocol, + ); + } + return undefined; + }, + ]; + } + + V1_getExtraConnectionProtocolDeserializers(): V1_ConnectionProtocolDeserializer[] { + return [ + (json: PlainObject): V1_Connection | undefined => { + if (json._type === V1_SERVICE_STORE_CONNECTION_PROTOCOL_TYPE) { + return deserialize(V1_serviceStoreConnectionModelSchema, json); + } + return undefined; + }, + ]; + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/ExternalStoreService_PureProtocolPlugin_Extension.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/ExternalStoreService_PureProtocolPlugin_Extension.ts new file mode 100644 index 0000000000..8e0730fe8b --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/ExternalStoreService_PureProtocolPlugin_Extension.ts @@ -0,0 +1,53 @@ +/** + * 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 type { PlainObject } from '@finos/legend-shared'; +import type { V1_SecurityScheme } from './v1/model/packageableElements/store/serviceStore/model/V1_SecurityScheme'; +import type { SecurityScheme } from '../../metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme'; +import type { + V1_GraphBuilderContext, + V1_GraphTransformerContext, + PureProtocolProcessorPlugin, +} from '@finos/legend-graph'; + +export type V1_SecuritySchemeBuilder = ( + connection: V1_SecurityScheme, + context: V1_GraphBuilderContext, +) => SecurityScheme | undefined; + +export type V1_SecuritySchemeTransformer = ( + metamodel: SecurityScheme, + context: V1_GraphTransformerContext, +) => V1_SecurityScheme | undefined; + +export type V1_SecuritySchemeProtocolSerializer = ( + connection: V1_SecurityScheme, +) => PlainObject | undefined; + +export type V1_SecuritySchemeProtocolDeserializer = ( + json: PlainObject, +) => V1_SecurityScheme | undefined; + +export interface ExternalStoreService_PureProtocolPlugin_Extension + extends PureProtocolProcessorPlugin { + V1_getExtraSecuritySchemeBuilders?(): V1_SecuritySchemeBuilder[]; + + V1_getExtraSecuritySchemeTransformers?(): V1_SecuritySchemeTransformer[]; + + V1_getExtraSecuritySchemeProtocolSerializers?(): V1_SecuritySchemeProtocolSerializer[]; + + V1_getExtraSecuritySchemeProtocolDeserializers?(): V1_SecuritySchemeProtocolDeserializer[]; +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/connection/V1_ServicestoreConnection.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/connection/V1_ServicestoreConnection.ts new file mode 100644 index 0000000000..3c7955f1d3 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/connection/V1_ServicestoreConnection.ts @@ -0,0 +1,40 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { V1_ConnectionVisitor } from '@finos/legend-graph'; +import { V1_Connection } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export class V1_ServiceStoreConnection + extends V1_Connection + implements Hashable +{ + baseUrl!: string; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE_CONNECTION, + this.store ?? '', + this.baseUrl, + ]); + } + + accept_ConnectionVisitor(visitor: V1_ConnectionVisitor): T { + return visitor.visit_Connection(this); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_LocalMappingProperty.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_LocalMappingProperty.ts new file mode 100644 index 0000000000..df155c7cac --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_LocalMappingProperty.ts @@ -0,0 +1,35 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { V1_Multiplicity } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export class V1_LocalMappingProperty implements Hashable { + name!: string; + type!: string; + multiplicity!: V1_Multiplicity; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.LOCAL_MAPPING_PROPERTY, + this.name, + this.type, + this.multiplicity, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping.ts new file mode 100644 index 0000000000..ddf159ca9a --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping.ts @@ -0,0 +1,36 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { V1_RawLambda } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import { V1_ServiceParameterMapping } from './V1_ServiceParameterMapping'; + +export class V1_ParameterIndexedParameterMapping + extends V1_ServiceParameterMapping + implements Hashable +{ + transform!: V1_RawLambda; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.PARAMETER_INDEXED_PARAMETER_MAPPING, + this.serviceParameter, + this.transform, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping.ts new file mode 100644 index 0000000000..0de940ed38 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping.ts @@ -0,0 +1,35 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import { V1_ServiceParameterMapping } from './V1_ServiceParameterMapping'; + +export class V1_PropertyIndexedParameterMapping + extends V1_ServiceParameterMapping + implements Hashable +{ + property!: string; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.PROPERTY_INDEXED_PARAMETER_MAPPING, + this.serviceParameter, + this.property, + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_RootServiceStoreClassMapping.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_RootServiceStoreClassMapping.ts new file mode 100644 index 0000000000..38aadcd0c3 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_RootServiceStoreClassMapping.ts @@ -0,0 +1,46 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { V1_ClassMapping } from '@finos/legend-graph'; +import type { V1_ClassMappingVisitor } from '@finos/legend-graph'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import type { V1_LocalMappingProperty } from './V1_LocalMappingProperty'; +import type { V1_ServiceMapping } from './V1_ServiceMapping'; + +export class V1_RootServiceStoreClassMapping + extends V1_ClassMapping + implements Hashable +{ + localMappingProperties: V1_LocalMappingProperty[] = []; + servicesMapping: V1_ServiceMapping[] = []; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.ROOT_SERVICE_STORE_CLASS_MAPPING, + this.id ?? '', + this.class ?? '', + this.root.toString(), + hashArray(this.localMappingProperties), + hashArray(this.servicesMapping), + ]); + } + + accept_ClassMappingVisitor(visitor: V1_ClassMappingVisitor): T { + return visitor.visit_ClassMapping(this); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceMapping.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceMapping.ts new file mode 100644 index 0000000000..b1cb03f145 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceMapping.ts @@ -0,0 +1,34 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import type { V1_ServiceStoreServicePtr } from '../model/V1_ServiceStoreServicePtr'; +import type { V1_ServiceParameterMapping } from './V1_ServiceParameterMapping'; + +export class V1_ServiceMapping implements Hashable { + service!: V1_ServiceStoreServicePtr; + parameterMappings: V1_ServiceParameterMapping[] = []; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_MAPPING, + this.service.service, + hashArray(this.parameterMappings), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping.ts new file mode 100644 index 0000000000..5d1f6d384f --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping.ts @@ -0,0 +1,23 @@ +/** + * 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 type { Hashable } from '@finos/legend-shared'; + +export abstract class V1_ServiceParameterMapping implements Hashable { + serviceParameter!: string; + + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SecurityScheme.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SecurityScheme.ts new file mode 100644 index 0000000000..86dc99eedb --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SecurityScheme.ts @@ -0,0 +1,21 @@ +/** + * 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 type { Hashable } from '@finos/legend-shared'; + +export abstract class V1_SecurityScheme implements Hashable { + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SerializationFormat.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SerializationFormat.ts new file mode 100644 index 0000000000..3cfd22d01a --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_SerializationFormat.ts @@ -0,0 +1,32 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export class V1_SerializationFormat implements Hashable { + style?: string | undefined; + explode?: boolean | undefined; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERIALIZATION_FORMAT, + this.style ?? '', + this.explode?.toString() ?? '', + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroup.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroup.ts new file mode 100644 index 0000000000..df56334344 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroup.ts @@ -0,0 +1,36 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import { V1_ServiceStoreElement } from './V1_ServiceStoreElement'; + +export class V1_ServiceGroup + extends V1_ServiceStoreElement + implements Hashable +{ + elements: V1_ServiceStoreElement[] = []; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_GROUP, + this.id, + this.path, + hashArray(this.elements), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr.ts new file mode 100644 index 0000000000..e34fc6d0c9 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr.ts @@ -0,0 +1,34 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export class V1_ServiceGroupPtr implements Hashable { + serviceStore!: string; + serviceGroup!: string; + parent?: V1_ServiceGroupPtr | undefined; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_GROUP_PTR, + this.serviceStore, + this.serviceGroup, + this.parent ?? '', + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceParameter.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceParameter.ts new file mode 100644 index 0000000000..7e7401609a --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceParameter.ts @@ -0,0 +1,40 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import type { V1_SerializationFormat } from './V1_SerializationFormat'; +import type { V1_TypeReference } from './V1_TypeReference'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export class V1_ServiceParameter implements Hashable { + name!: string; + type!: V1_TypeReference; + location!: string; + enumeration?: string | undefined; + serializationFormat?: V1_SerializationFormat | undefined; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_PARAMETER, + this.name, + this.type, + this.location, + this.enumeration ?? '', + this.serializationFormat ?? '', + ]); + } +} diff --git a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/store/relational/V1_ServiceStore.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStore.ts similarity index 64% rename from packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/store/relational/V1_ServiceStore.ts rename to packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStore.ts index ceca6920e9..e98d6374ca 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/store/relational/V1_ServiceStore.ts +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStore.ts @@ -16,25 +16,27 @@ import { hashArray } from '@finos/legend-shared'; import type { Hashable } from '@finos/legend-shared'; -import { CORE_HASH_STRUCTURE } from '../../../../../../../../MetaModelConst'; -import { V1_Store } from '../../../../model/packageableElements/store/V1_Store'; -import type { V1_PackageableElementVisitor } from '../../../../model/packageableElements/V1_PackageableElement'; +import type { V1_PackageableElementVisitor } from '@finos/legend-graph'; +import { V1_Store } from '@finos/legend-graph'; +import type { V1_ServiceStoreElement } from './V1_ServiceStoreElement'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; export class V1_ServiceStore extends V1_Store implements Hashable { - docLink!: string; + description?: string | undefined; + elements: V1_ServiceStoreElement[] = []; override get hashCode(): string { return hashArray([ - CORE_HASH_STRUCTURE.SERVICE_STORE, + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE, this.path, - hashArray(this.includedStores), - this.docLink, + this.description ?? '', + hashArray(this.elements), ]); } accept_PackageableElementVisitor( visitor: V1_PackageableElementVisitor, ): T { - return visitor.visit_ServiceStore(this); + return visitor.visit_PackageableElement(this); } } diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement.ts new file mode 100644 index 0000000000..d180f8d76d --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement.ts @@ -0,0 +1,25 @@ +/** + * 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 type { Hashable } from '@finos/legend-shared'; + +export abstract class V1_ServiceStoreElement implements Hashable { + private readonly _$nominalTypeBrand!: 'V1_ServiceStoreElement'; + id!: string; + path!: string; + + abstract get hashCode(): string; +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreService.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreService.ts new file mode 100644 index 0000000000..3f9abb39ab --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreService.ts @@ -0,0 +1,50 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import { V1_ServiceStoreElement } from './V1_ServiceStoreElement'; +import type { V1_ServiceParameter } from './V1_ServiceParameter'; +import type { V1_SecurityScheme } from './V1_SecurityScheme'; +import type { + V1_TypeReference, + V1_ComplexTypeReference, +} from './V1_TypeReference'; + +export class V1_ServiceStoreService + extends V1_ServiceStoreElement + implements Hashable +{ + requestBody?: V1_TypeReference | undefined; + method!: string; + parameters: V1_ServiceParameter[] = []; + response!: V1_ComplexTypeReference; + security: V1_SecurityScheme[] = []; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE_SERVICE, + this.id, + this.path, + this.requestBody ?? '', + this.method, + hashArray(this.parameters), + this.response, + hashArray(this.security), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr.ts new file mode 100644 index 0000000000..e43e50f7da --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr.ts @@ -0,0 +1,35 @@ +/** + * 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 { hashArray } from '@finos/legend-shared'; +import type { Hashable } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; +import type { V1_ServiceGroupPtr } from './V1_ServiceGroupPtr'; + +export class V1_ServiceStoreServicePtr implements Hashable { + serviceStore!: string; + service!: string; + parent?: V1_ServiceGroupPtr | undefined; + + get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.SERVICE_STORE_SERVICE_PTR, + this.serviceStore, + this.service, + this.parent ?? '', + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_TypeReference.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_TypeReference.ts new file mode 100644 index 0000000000..b7b56d52c7 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/model/packageableElements/store/serviceStore/model/V1_TypeReference.ts @@ -0,0 +1,91 @@ +/** + * 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 type { Hashable } from '@finos/legend-shared'; +import { hashArray } from '@finos/legend-shared'; +import { SERVICE_STORE_HASH_STRUCTURE } from '../../../../../../../../ESService_ModelUtils'; + +export abstract class V1_TypeReference implements Hashable { + private readonly _$nominalTypeBrand!: 'V1_TypeReference'; + list!: boolean; + + abstract get hashCode(): string; +} + +export class V1_ComplexTypeReference + extends V1_TypeReference + implements Hashable +{ + type!: string; + binding!: string; + + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.COMPLEX_TYPE_REFERENCE, + this.list.toString(), + this.type, + this.binding, + ]); + } +} + +export class V1_BooleanTypeReference + extends V1_TypeReference + implements Hashable +{ + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.BOOLEAN_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class V1_FloatTypeReference + extends V1_TypeReference + implements Hashable +{ + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.FLOAT_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class V1_IntegerTypeReference + extends V1_TypeReference + implements Hashable +{ + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.INTEGER_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} + +export class V1_StringTypeReference + extends V1_TypeReference + implements Hashable +{ + override get hashCode(): string { + return hashArray([ + SERVICE_STORE_HASH_STRUCTURE.STRING_TYPE_REFERENCE, + this.list.toString(), + ]); + } +} diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_GraphBuilderHelper.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_GraphBuilderHelper.ts new file mode 100644 index 0000000000..932467ec2b --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_GraphBuilderHelper.ts @@ -0,0 +1,317 @@ +/** + * 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 { getServiceStore } from '../../../../../../graphManager/ESService_GraphManagerHelper'; +import type { ServiceStore } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStore'; +import type { + PackageableElementImplicitReference, + V1_GraphBuilderContext, +} from '@finos/legend-graph'; +import type { V1_ServiceStoreServicePtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr'; +import { + ServiceStoreService, + HTTP_METHOD, +} from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService'; +import type { V1_ServiceGroupPtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr'; +import { ServiceGroup } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup'; +import type { V1_TypeReference } from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import { + V1_BooleanTypeReference, + V1_ComplexTypeReference, + V1_FloatTypeReference, + V1_IntegerTypeReference, + V1_StringTypeReference, +} from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import type { TypeReference } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference'; +import { + BooleanTypeReference, + ComplexTypeReference, + FloatTypeReference, + IntegerTypeReference, + StringTypeReference, +} from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference'; +import { getBinding } from '@finos/legend-extension-dsl-serializer'; +import { + assertNonNullable, + guaranteeNonEmptyString, + guaranteeNonNullable, + UnsupportedOperationError, +} from '@finos/legend-shared'; +import type { V1_ServiceParameter } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceParameter'; +import { + LOCATION, + ServiceParameter, +} from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter'; +import type { V1_ServiceParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping'; +import type { ServiceParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceParameterMapping'; +import { V1_ParameterIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping'; +import { RawLambda } from '@finos/legend-graph'; +import { V1_PropertyIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping'; +import type { V1_ServiceStoreElement } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement'; +import type { ServiceStoreElement } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement'; +import { V1_ServiceStoreService } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreService'; +import { V1_ServiceGroup } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroup'; +import type { SecurityScheme } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme'; +import type { V1_SecurityScheme } from '../../model/packageableElements/store/serviceStore/model/V1_SecurityScheme'; +import type { ExternalStoreService_PureProtocolPlugin_Extension } from '../../../ExternalStoreService_PureProtocolPlugin_Extension'; +import { SerializationFormat } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/SerializationFormat'; +import type { V1_SerializationFormat } from '../../model/packageableElements/store/serviceStore/model/V1_SerializationFormat'; +import { + getServiceStoreService, + getServiceGroup, + getParameter, +} from '../../../../../../helpers/ESService_Helper'; +import { ParameterIndexedParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/ParameterIndexedParameterMapping'; +import { PropertyIndexedParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/PropertyIndexedParameterMapping'; + +export const V1_resolveServiceStore = ( + path: string, + context: V1_GraphBuilderContext, +): PackageableElementImplicitReference => + context.createImplicitPackageableElementReference(path, (_path: string) => + getServiceStore(_path, context.graph), + ); + +export const V1_resolveServiceGroup = ( + serviceGroupPtr: V1_ServiceGroupPtr, + store: PackageableElementImplicitReference, +): ServiceGroup => { + if (serviceGroupPtr.parent === undefined) { + return getServiceGroup(store.value.elements, serviceGroupPtr.serviceGroup); + } else { + const parentServiceGroup = V1_resolveServiceGroup( + serviceGroupPtr.parent, + store, + ); + return getServiceGroup( + parentServiceGroup.elements, + serviceGroupPtr.serviceGroup, + ); + } +}; + +export const V1_resolveService = ( + servicePtr: V1_ServiceStoreServicePtr, + context: V1_GraphBuilderContext, +): ServiceStoreService => { + const serviceStore = V1_resolveServiceStore(servicePtr.serviceStore, context); + if (servicePtr.parent === undefined) { + return getServiceStoreService( + serviceStore.value.elements, + servicePtr.service, + ); + } else { + const parentServiceGroup = V1_resolveServiceGroup( + servicePtr.parent, + serviceStore, + ); + return getServiceStoreService( + parentServiceGroup.elements, + servicePtr.service, + ); + } +}; + +export const V1_buildTypeReference = ( + protocol: V1_TypeReference, + context: V1_GraphBuilderContext, +): TypeReference => { + if (protocol instanceof V1_BooleanTypeReference) { + const booleanTypeReference = new BooleanTypeReference(); + booleanTypeReference.list = protocol.list; + return booleanTypeReference; + } else if (protocol instanceof V1_ComplexTypeReference) { + const complexTypeReference = new ComplexTypeReference(); + complexTypeReference.list = protocol.list; + complexTypeReference.type = context.graph.getClass(protocol.type); + complexTypeReference.binding = getBinding(protocol.binding, context.graph); + return complexTypeReference; + } else if (protocol instanceof V1_FloatTypeReference) { + const floatTypeReference = new FloatTypeReference(); + floatTypeReference.list = protocol.list; + return floatTypeReference; + } else if (protocol instanceof V1_IntegerTypeReference) { + const integerTypeReference = new IntegerTypeReference(); + integerTypeReference.list = protocol.list; + return integerTypeReference; + } else if (protocol instanceof V1_StringTypeReference) { + const stringTypeReference = new StringTypeReference(); + stringTypeReference.list = protocol.list; + return stringTypeReference; + } + throw new UnsupportedOperationError(`Can't build type reference`, protocol); +}; + +const V1_buildSerializationFormat = ( + protocol: V1_SerializationFormat, +): SerializationFormat => { + const serializationFormat = new SerializationFormat(); + serializationFormat.style = protocol.style; + serializationFormat.explode = protocol.explode; + return serializationFormat; +}; + +export const V1_buildServiceParameter = ( + protocol: V1_ServiceParameter, + context: V1_GraphBuilderContext, +): ServiceParameter => { + const serviceParameter = new ServiceParameter(); + serviceParameter.name = guaranteeNonEmptyString( + protocol.name, + `Service paramater 'name' field is missing or empty`, + ); + assertNonNullable(protocol.type, `Service parameter 'type' field is missing`); + serviceParameter.type = V1_buildTypeReference(protocol.type, context); + serviceParameter.location = guaranteeNonNullable( + Object.values(LOCATION).find((type) => type === protocol.location), + `Service parameter location '${protocol.location}' is not supported`, + ); + serviceParameter.enumeration = protocol.enumeration; + if (protocol.serializationFormat !== undefined) { + serviceParameter.serializationFormat = V1_buildSerializationFormat( + protocol.serializationFormat, + ); + } + return serviceParameter; +}; + +export const V1_buildServiceParameterMapping = ( + protocol: V1_ServiceParameterMapping, + service: ServiceStoreService, +): ServiceParameterMapping => { + if (protocol instanceof V1_ParameterIndexedParameterMapping) { + const mapping = new ParameterIndexedParameterMapping(); + mapping.serviceParameter = getParameter( + protocol.serviceParameter, + service.parameters, + ); + const lambda = new RawLambda( + protocol.transform.parameters, + protocol.transform.body, + ); + mapping.transform = lambda; + return mapping; + } else if (protocol instanceof V1_PropertyIndexedParameterMapping) { + const mapping = new PropertyIndexedParameterMapping(); + mapping.serviceParameter = getParameter( + protocol.serviceParameter, + service.parameters, + ); + mapping.property = protocol.property; + return mapping; + } + throw new UnsupportedOperationError( + `Can't build service parameter mapping`, + protocol, + ); +}; + +const V1_buildSecurityScheme = ( + protocol: V1_SecurityScheme, + context: V1_GraphBuilderContext, +): SecurityScheme => { + const extraSecuritySchemeBuilders = context.extensions.plugins.flatMap( + (plugin) => + ( + plugin as ExternalStoreService_PureProtocolPlugin_Extension + ).V1_getExtraSecuritySchemeBuilders?.() ?? [], + ); + for (const builder of extraSecuritySchemeBuilders) { + const securityScheme = builder(protocol, context); + if (securityScheme) { + return securityScheme; + } + } + throw new UnsupportedOperationError( + `Can't build security scheme: no compatible builder available from plugins`, + protocol, + ); +}; + +export const V1_buildServiceStoreElement = ( + protocol: V1_ServiceStoreElement, + owner: ServiceStore, + context: V1_GraphBuilderContext, + parent?: ServiceGroup | undefined, +): ServiceStoreElement => { + if (protocol instanceof V1_ServiceStoreService) { + const service = new ServiceStoreService(); + service.id = guaranteeNonEmptyString( + protocol.id, + `Service 'id' field is missing or empty`, + ); + service.path = guaranteeNonEmptyString( + protocol.path, + `Service 'path' field is missing or empty`, + ); + service.owner = owner; + service.parent = parent; + if (protocol.requestBody !== undefined) { + service.requestBody = V1_buildTypeReference( + protocol.requestBody, + context, + ); + } + service.method = guaranteeNonNullable( + Object.values(HTTP_METHOD).find((type) => type === protocol.method), + `Service method '${protocol.method}' is not supported`, + ); + service.parameters = protocol.parameters.map((parameter) => + V1_buildServiceParameter(parameter, context), + ); + assertNonNullable(protocol.response, `Service 'response' field is missing`); + service.response = new ComplexTypeReference(); + service.response.list = protocol.response.list; + service.response.type = context.graph.getClass( + guaranteeNonEmptyString( + protocol.response.type, + `Service response 'type' field is missing or empty`, + ), + ); + service.response.binding = getBinding( + guaranteeNonEmptyString( + protocol.response.binding, + `Service response 'binding' field is missing or empty`, + ), + context.graph, + ); + service.security = protocol.security.map((securityScheme) => + V1_buildSecurityScheme(securityScheme, context), + ); + return service; + } else if (protocol instanceof V1_ServiceGroup) { + const serviceGroup = new ServiceGroup(); + serviceGroup.id = guaranteeNonEmptyString( + protocol.id, + `Service group 'id' field is missing or empty`, + ); + serviceGroup.path = guaranteeNonEmptyString( + protocol.path, + `Service group 'path' field is missing or empty`, + ); + serviceGroup.owner = owner; + serviceGroup.parent = parent; + + serviceGroup.elements = protocol.elements.map((element) => + V1_buildServiceStoreElement(element, owner, context, serviceGroup), + ); + return serviceGroup; + } + throw new UnsupportedOperationError( + `Can't build service store element`, + protocol, + ); +}; diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_TransformerHelper.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_TransformerHelper.ts new file mode 100644 index 0000000000..072e3bc7a0 --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureGraph/V1_ESService_TransformerHelper.ts @@ -0,0 +1,241 @@ +/** + * 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 { + StringTypeReference, + BooleanTypeReference, + FloatTypeReference, + IntegerTypeReference, + ComplexTypeReference, +} from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference'; +import { + V1_StringTypeReference, + V1_BooleanTypeReference, + V1_FloatTypeReference, + V1_ComplexTypeReference, + V1_IntegerTypeReference, +} from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import type { TypeReference } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/TypeReference'; +import type { V1_TypeReference } from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import { UnsupportedOperationError } from '@finos/legend-shared'; +import type { ServiceParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/ServiceParameterMapping'; +import type { V1_ServiceParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping'; +import { V1_ParameterIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping'; +import type { V1_GraphTransformerContext } from '@finos/legend-graph'; +import { V1_RawLambda } from '@finos/legend-graph'; +import { V1_PropertyIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping'; +import type { ServiceParameter } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceParameter'; +import { V1_ServiceParameter } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceParameter'; +import { ServiceStoreService } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreService'; +import { V1_ServiceStoreService } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreService'; +import { ServiceGroup } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceGroup'; +import { V1_ServiceGroup } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroup'; +import { V1_ServiceGroupPtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr'; +import { V1_ServiceStoreServicePtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr'; +import type { ServiceStoreElement } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/ServiceStoreElement'; +import type { V1_ServiceStoreElement } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement'; +import type { V1_SecurityScheme } from '../../model/packageableElements/store/serviceStore/model/V1_SecurityScheme'; +import type { SecurityScheme } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/model/SecurityScheme'; +import type { ExternalStoreService_PureProtocolPlugin_Extension } from '../../../ExternalStoreService_PureProtocolPlugin_Extension'; +import { ParameterIndexedParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/ParameterIndexedParameterMapping'; +import { PropertyIndexedParameterMapping } from '../../../../../metamodels/pure/model/packageableElements/store/serviceStore/mapping/PropertyIndexedParameterMapping'; + +export const V1_transformStringTypeReference = ( + metamodel: StringTypeReference, +): V1_StringTypeReference => { + const stringTypeReference = new V1_StringTypeReference(); + stringTypeReference.list = metamodel.list; + return stringTypeReference; +}; + +export const V1_transformBooleanTypeReference = ( + metamodel: BooleanTypeReference, +): V1_BooleanTypeReference => { + const booleanTypeReference = new V1_BooleanTypeReference(); + booleanTypeReference.list = metamodel.list; + return booleanTypeReference; +}; + +export const V1_transformFloatTypeReference = ( + metamodel: FloatTypeReference, +): V1_FloatTypeReference => { + const floatTypeReference = new V1_FloatTypeReference(); + floatTypeReference.list = metamodel.list; + return floatTypeReference; +}; + +export const V1_transformIntegerTypeReference = ( + metamodel: IntegerTypeReference, +): V1_IntegerTypeReference => { + const integerTypeReference = new V1_IntegerTypeReference(); + integerTypeReference.list = metamodel.list; + return integerTypeReference; +}; + +export const V1_transformComplexTypeReference = ( + metamodel: ComplexTypeReference, +): V1_ComplexTypeReference => { + const complexTypeReference = new V1_ComplexTypeReference(); + complexTypeReference.list = metamodel.list; + complexTypeReference.type = metamodel.type.path; + complexTypeReference.binding = metamodel.binding.path; + return complexTypeReference; +}; + +export const V1_transformTypeReference = ( + metamodel: TypeReference, +): V1_TypeReference => { + if (metamodel instanceof BooleanTypeReference) { + return V1_transformBooleanTypeReference(metamodel); + } else if (metamodel instanceof ComplexTypeReference) { + return V1_transformComplexTypeReference(metamodel); + } else if (metamodel instanceof FloatTypeReference) { + return V1_transformFloatTypeReference(metamodel); + } else if (metamodel instanceof IntegerTypeReference) { + return V1_transformIntegerTypeReference(metamodel); + } else if (metamodel instanceof StringTypeReference) { + return V1_transformStringTypeReference(metamodel); + } + throw new UnsupportedOperationError( + `Can't transform type reference`, + metamodel, + ); +}; + +export const V1_transformServiceParameterMapping = ( + metamodel: ServiceParameterMapping, +): V1_ServiceParameterMapping => { + if (metamodel instanceof ParameterIndexedParameterMapping) { + const mapping = new V1_ParameterIndexedParameterMapping(); + mapping.serviceParameter = metamodel.serviceParameter.name; + const lambda = new V1_RawLambda(); + lambda.parameters = metamodel.transform.parameters; + lambda.body = metamodel.transform.body; + mapping.transform = lambda; + return mapping; + } else if (metamodel instanceof PropertyIndexedParameterMapping) { + const mapping = new V1_PropertyIndexedParameterMapping(); + mapping.serviceParameter = metamodel.serviceParameter.name; + mapping.property = metamodel.property; + return mapping; + } + throw new UnsupportedOperationError( + `Can't transform service parameter mapping`, + metamodel, + ); +}; + +export const V1_transformServiceParameter = ( + metamodel: ServiceParameter, +): V1_ServiceParameter => { + const serviceParameter = new V1_ServiceParameter(); + serviceParameter.name = metamodel.name; + serviceParameter.type = V1_transformTypeReference(metamodel.type); + serviceParameter.location = metamodel.location; + serviceParameter.enumeration = metamodel.enumeration; + serviceParameter.serializationFormat = metamodel.serializationFormat; + return serviceParameter; +}; + +const V1_transformSecurityScheme = ( + metamodel: SecurityScheme, + context: V1_GraphTransformerContext, +): V1_SecurityScheme => { + const extraSecuritySchemeTransformers = context.plugins.flatMap( + (plugin) => + ( + plugin as ExternalStoreService_PureProtocolPlugin_Extension + ).V1_getExtraSecuritySchemeTransformers?.() ?? [], + ); + for (const transformer of extraSecuritySchemeTransformers) { + const protocol = transformer(metamodel, context); + if (protocol) { + return protocol; + } + } + throw new UnsupportedOperationError( + `Can't transform security scheme: no compatible transformer available from plugins`, + metamodel, + ); +}; + +export const V1_transformServiceStoreService = ( + metamodel: ServiceStoreService, + context: V1_GraphTransformerContext, +): V1_ServiceStoreService => { + const service = new V1_ServiceStoreService(); + service.id = metamodel.id; + service.path = metamodel.path; + if (metamodel.requestBody !== undefined) { + service.requestBody = V1_transformTypeReference(metamodel.requestBody); + } + service.method = metamodel.method; + service.parameters = metamodel.parameters.map((parameter) => + V1_transformServiceParameter(parameter), + ); + service.response = V1_transformComplexTypeReference(metamodel.response); + service.security = metamodel.security.map((securityScheme) => + V1_transformSecurityScheme(securityScheme, context), + ); + return service; +}; + +export const V1_transformServiceToServiceGroupPtr = ( + metamodel: ServiceGroup, +): V1_ServiceGroupPtr => { + const serviceGroup = new V1_ServiceGroupPtr(); + serviceGroup.serviceGroup = metamodel.id; + serviceGroup.serviceStore = metamodel.owner.path; + if (metamodel.parent !== undefined) { + serviceGroup.parent = V1_transformServiceToServiceGroupPtr( + metamodel.parent, + ); + } + return serviceGroup; +}; + +export const V1_transformServiceToServicePtr = ( + metamodel: ServiceStoreService, +): V1_ServiceStoreServicePtr => { + const service = new V1_ServiceStoreServicePtr(); + service.service = metamodel.id; + service.serviceStore = metamodel.owner.path; + if (metamodel.parent !== undefined) { + service.parent = V1_transformServiceToServiceGroupPtr(metamodel.parent); + } + return service; +}; + +export const V1_transformServiceStoreElement = ( + metamodel: ServiceStoreElement, + context: V1_GraphTransformerContext, +): V1_ServiceStoreElement => { + if (metamodel instanceof ServiceStoreService) { + return V1_transformServiceStoreService(metamodel, context); + } else if (metamodel instanceof ServiceGroup) { + const serviceGroup = new V1_ServiceGroup(); + serviceGroup.id = metamodel.id; + serviceGroup.path = metamodel.path; + serviceGroup.elements = metamodel.elements.map((element) => + V1_transformServiceStoreElement(element, context), + ); + return serviceGroup; + } + throw new UnsupportedOperationError( + `Can't transform service store element`, + metamodel, + ); +}; diff --git a/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureProtocol/V1_ESService_ProtocolHelper.ts b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureProtocol/V1_ESService_ProtocolHelper.ts new file mode 100644 index 0000000000..3313a01a0a --- /dev/null +++ b/packages/legend-extension-external-store-service/src/models/protocols/pure/v1/transformation/pureProtocol/V1_ESService_ProtocolHelper.ts @@ -0,0 +1,459 @@ +/** + * 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 type { PlainObject } from '@finos/legend-shared'; +import { + UnsupportedOperationError, + usingConstantValueSchema, + usingModelSchema, +} from '@finos/legend-shared'; +import type { ModelSchema } from 'serializr'; +import { + alias, + createModelSchema, + primitive, + list, + optional, + custom, + serialize, + deserialize, + object, +} from 'serializr'; +import { V1_ServiceStore } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStore'; +import { V1_ServiceStoreService } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreService'; +import { V1_ServiceGroup } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroup'; +import type { V1_ServiceStoreElement } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreElement'; +import { V1_ServiceParameter } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceParameter'; +import type { V1_TypeReference } from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import { + V1_BooleanTypeReference, + V1_ComplexTypeReference, + V1_FloatTypeReference, + V1_IntegerTypeReference, + V1_StringTypeReference, +} from '../../model/packageableElements/store/serviceStore/model/V1_TypeReference'; +import { V1_SerializationFormat } from '../../model/packageableElements/store/serviceStore/model/V1_SerializationFormat'; +import { V1_ServiceStoreConnection } from '../../model/packageableElements/store/serviceStore/connection/V1_ServicestoreConnection'; +import { V1_RootServiceStoreClassMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_RootServiceStoreClassMapping'; +import { V1_LocalMappingProperty } from '../../model/packageableElements/store/serviceStore/mapping/V1_LocalMappingProperty'; +import { V1_ServiceMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ServiceMapping'; +import { V1_ServiceStoreServicePtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceStoreServicePtr'; +import { V1_ServiceGroupPtr } from '../../model/packageableElements/store/serviceStore/model/V1_ServiceGroupPtr'; +import type { V1_ServiceParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ServiceParameterMapping'; +import type { PureProtocolProcessorPlugin } from '@finos/legend-graph'; +import { V1_Multiplicity, V1_rawLambdaModelSchema } from '@finos/legend-graph'; +import { V1_ParameterIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_ParameterIndexedParameterMapping'; +import { V1_PropertyIndexedParameterMapping } from '../../model/packageableElements/store/serviceStore/mapping/V1_PropertyIndexedParameterMapping'; +import type { V1_SecurityScheme } from '../../model/packageableElements/store/serviceStore/model/V1_SecurityScheme'; +import type { ExternalStoreService_PureProtocolPlugin_Extension } from '../../../ExternalStoreService_PureProtocolPlugin_Extension'; + +export const V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE = 'serviceStore'; +export const V1_SERVICE_STORE_MAPPING_PROTOCOL_TYPE = 'serviceStore'; +export const V1_SERVICE_STORE_CONNECTION_PROTOCOL_TYPE = 'serviceStore'; + +enum V1_ServiceStoreElementType { + SERVICE = 'service', + SERVICE_GROUP = 'serviceGroup', +} + +enum V1_ReferenceType { + BOOLEAN_TYPE_REFERENCE = 'boolean', + COMPLEX_TYPE_REFERENCE = 'complex', + FLOAT_TYPE_REFERENCE = 'float', + INTEGER_TYPE_REFERENCE = 'integer', + STRING_TYPE_REFERENCE = 'string', +} + +enum V1_ServiceParameterMappingType { + PROPERTY_INDEXED_PARAMETER_MAPPING = 'property', + PARAMETER_INDEXED_PARAMETER_MAPPING = 'parameter', +} + +const V1_booleanTypeReferenceModelSchema = createModelSchema( + V1_BooleanTypeReference, + { + _type: usingConstantValueSchema(V1_ReferenceType.BOOLEAN_TYPE_REFERENCE), + list: primitive(), + }, +); + +const V1_floatTypeReferenceModelSchema = createModelSchema( + V1_FloatTypeReference, + { + _type: usingConstantValueSchema(V1_ReferenceType.FLOAT_TYPE_REFERENCE), + list: primitive(), + }, +); + +const V1_integerTypeReferenceModelSchema = createModelSchema( + V1_IntegerTypeReference, + { + _type: usingConstantValueSchema(V1_ReferenceType.INTEGER_TYPE_REFERENCE), + list: primitive(), + }, +); + +const V1_stringTypeReferenceModelSchema = createModelSchema( + V1_StringTypeReference, + { + _type: usingConstantValueSchema(V1_ReferenceType.STRING_TYPE_REFERENCE), + list: primitive(), + }, +); + +const V1_complexTypeReferenceModelSchema = createModelSchema( + V1_ComplexTypeReference, + { + _type: usingConstantValueSchema(V1_ReferenceType.COMPLEX_TYPE_REFERENCE), + binding: primitive(), + list: primitive(), + type: primitive(), + }, +); + +const V1_serializeTypeReference = ( + protocol: V1_TypeReference, +): PlainObject => { + if (protocol instanceof V1_BooleanTypeReference) { + return serialize(V1_booleanTypeReferenceModelSchema, protocol); + } else if (protocol instanceof V1_ComplexTypeReference) { + return serialize(V1_complexTypeReferenceModelSchema, protocol); + } else if (protocol instanceof V1_FloatTypeReference) { + return serialize(V1_floatTypeReferenceModelSchema, protocol); + } else if (protocol instanceof V1_IntegerTypeReference) { + return serialize(V1_integerTypeReferenceModelSchema, protocol); + } else if (protocol instanceof V1_StringTypeReference) { + return serialize(V1_stringTypeReferenceModelSchema, protocol); + } + throw new UnsupportedOperationError( + `Can't serialize type reference`, + protocol, + ); +}; + +const V1_deserializeTypeReference = ( + json: PlainObject, +): V1_TypeReference => { + switch (json._type) { + case V1_ReferenceType.STRING_TYPE_REFERENCE: + return deserialize(V1_stringTypeReferenceModelSchema, json); + case V1_ReferenceType.BOOLEAN_TYPE_REFERENCE: + return deserialize(V1_booleanTypeReferenceModelSchema, json); + case V1_ReferenceType.FLOAT_TYPE_REFERENCE: + return deserialize(V1_floatTypeReferenceModelSchema, json); + case V1_ReferenceType.COMPLEX_TYPE_REFERENCE: + return deserialize(V1_complexTypeReferenceModelSchema, json); + case V1_ReferenceType.INTEGER_TYPE_REFERENCE: + return deserialize(V1_integerTypeReferenceModelSchema, json); + default: { + throw new UnsupportedOperationError( + `Can't deserialize type reference of type '${json._type}'`, + ); + } + } +}; + +const V1_serializationFormatModelSchema = createModelSchema( + V1_SerializationFormat, + { + explode: optional(primitive()), + style: optional(primitive()), + }, +); + +const V1_serviceParameterModelSchema = createModelSchema(V1_ServiceParameter, { + enumeration: optional(primitive()), + location: primitive(), + name: primitive(), + serializationFormat: optional( + usingModelSchema(V1_serializationFormatModelSchema), + ), + type: custom( + (val) => V1_serializeTypeReference(val), + (val) => V1_deserializeTypeReference(val), + ), +}); + +const V1_serializeSecurityScheme = ( + protocol: V1_SecurityScheme, + plugins: PureProtocolProcessorPlugin[], +): PlainObject => { + const extraSecuritySchemeProtocolSerializers = plugins.flatMap( + (plugin) => + ( + plugin as ExternalStoreService_PureProtocolPlugin_Extension + ).V1_getExtraSecuritySchemeProtocolSerializers?.() ?? [], + ); + for (const serializer of extraSecuritySchemeProtocolSerializers) { + const json = serializer(protocol); + if (json) { + return json; + } + } + throw new UnsupportedOperationError( + `Can't serialize security scheme: no compatible serializer available from plugins`, + protocol, + ); +}; + +const V1_deserializeSecurityScheme = ( + json: PlainObject, + plugins: PureProtocolProcessorPlugin[], +): V1_SecurityScheme => { + const extraSecuritySchemeProtocolDeserializers = plugins.flatMap( + (plugin) => + ( + plugin as ExternalStoreService_PureProtocolPlugin_Extension + ).V1_getExtraSecuritySchemeProtocolDeserializers?.() ?? [], + ); + for (const deserializer of extraSecuritySchemeProtocolDeserializers) { + const protocol = deserializer(json); + if (protocol) { + return protocol; + } + } + throw new UnsupportedOperationError( + `Can't deserialize security scheme of type '${json._type}': no compatible deserializer available from plugins`, + ); +}; + +const V1_serviceModelSchema = ( + plugins: PureProtocolProcessorPlugin[], +): ModelSchema => + createModelSchema(V1_ServiceStoreService, { + _type: usingConstantValueSchema(V1_ServiceStoreElementType.SERVICE), + id: primitive(), + method: primitive(), + parameters: list(usingModelSchema(V1_serviceParameterModelSchema)), + path: primitive(), + requestBody: optional( + custom( + (val) => { + if (val !== undefined) { + return V1_serializeTypeReference(val); + } + return undefined; + }, + (val) => { + if (val !== undefined) { + return V1_deserializeTypeReference(val); + } + return undefined; + }, + ), + ), + response: usingModelSchema(V1_complexTypeReferenceModelSchema), + security: list( + custom( + (val) => V1_serializeSecurityScheme(val, plugins), + (val) => V1_deserializeSecurityScheme(val, plugins), + ), + ), + }); + +const V1_serviceGroupModelSchema = ( + plugins: PureProtocolProcessorPlugin[], +): ModelSchema => + createModelSchema(V1_ServiceGroup, { + _type: usingConstantValueSchema(V1_ServiceStoreElementType.SERVICE_GROUP), + elements: list( + custom( + (val) => { + if (val instanceof V1_ServiceStoreService) { + return serialize(V1_serviceModelSchema(plugins), val); + } else if (val instanceof V1_ServiceGroup) { + return serialize(V1_serviceGroupModelSchema(plugins), val); + } + throw new UnsupportedOperationError( + `Can't serialize service store element`, + val, + ); + }, + (val) => { + switch (val._type) { + case V1_ServiceStoreElementType.SERVICE: + return deserialize(V1_serviceModelSchema(plugins), val); + case V1_ServiceStoreElementType.SERVICE_GROUP: + return deserialize(V1_serviceGroupModelSchema(plugins), val); + default: { + throw new UnsupportedOperationError( + `Can't deserialize service store element of type '${val._type}'`, + ); + } + } + }, + ), + ), + id: primitive(), + path: primitive(), + }); + +const V1_serializeServiceStoreElement = ( + protocol: V1_ServiceStoreElement, + plugins: PureProtocolProcessorPlugin[], +): PlainObject => { + if (protocol instanceof V1_ServiceStoreService) { + return serialize(V1_serviceModelSchema(plugins), protocol); + } else if (protocol instanceof V1_ServiceGroup) { + return serialize(V1_serviceGroupModelSchema(plugins), protocol); + } + throw new UnsupportedOperationError( + `Can't serialize service store element`, + protocol, + ); +}; + +const V1_deserializeServiceStoreElement = ( + json: PlainObject, + plugins: PureProtocolProcessorPlugin[], +): V1_ServiceStoreElement => { + switch (json._type) { + case V1_ServiceStoreElementType.SERVICE: + return deserialize(V1_serviceModelSchema(plugins), json); + case V1_ServiceStoreElementType.SERVICE_GROUP: + return deserialize(V1_serviceGroupModelSchema(plugins), json); + default: { + throw new UnsupportedOperationError( + `Can't deserialize service store element of type '${json._type}'`, + ); + } + } +}; + +const V1_serviceGroupPtrModelSchema = createModelSchema(V1_ServiceGroupPtr, { + parent: optional(object(V1_ServiceGroupPtr)), + serviceStore: primitive(), + serviceGroup: primitive(), +}); + +const V1_servicePtrModelSchema = createModelSchema(V1_ServiceStoreServicePtr, { + parent: optional(usingModelSchema(V1_serviceGroupPtrModelSchema)), + service: primitive(), + serviceStore: primitive(), +}); + +const V1_parameterIndexedParameterMappingModelSchema = createModelSchema( + V1_ParameterIndexedParameterMapping, + { + _type: usingConstantValueSchema( + V1_ServiceParameterMappingType.PARAMETER_INDEXED_PARAMETER_MAPPING, + ), + serviceParameter: primitive(), + transform: usingModelSchema(V1_rawLambdaModelSchema), + }, +); + +const V1_propertyIndexedParameterMappingModelSchema = createModelSchema( + V1_PropertyIndexedParameterMapping, + { + _type: usingConstantValueSchema( + V1_ServiceParameterMappingType.PROPERTY_INDEXED_PARAMETER_MAPPING, + ), + property: primitive(), + serviceParameter: primitive(), + }, +); + +const V1_serializeServiceParameterMapping = ( + protocol: V1_ServiceParameterMapping, +): PlainObject => { + if (protocol instanceof V1_ParameterIndexedParameterMapping) { + return serialize(V1_parameterIndexedParameterMappingModelSchema, protocol); + } else if (protocol instanceof V1_PropertyIndexedParameterMapping) { + return serialize(V1_propertyIndexedParameterMappingModelSchema, protocol); + } + throw new UnsupportedOperationError( + `Can't serialize service parameter mapping`, + protocol, + ); +}; + +const V1_deserializeServiceParameterMapping = ( + json: PlainObject, +): V1_ServiceParameterMapping => { + switch (json._type) { + case 'parameter': + return deserialize(V1_parameterIndexedParameterMappingModelSchema, json); + case 'property': + return deserialize(V1_propertyIndexedParameterMappingModelSchema, json); + default: { + throw new UnsupportedOperationError( + `Can't deserialize service store element of type '${json._type}'`, + ); + } + } +}; + +const V1_serviceMappingModelSchema = createModelSchema(V1_ServiceMapping, { + parameterMappings: list( + custom( + (val) => V1_serializeServiceParameterMapping(val), + (val) => V1_deserializeServiceParameterMapping(val), + ), + ), + service: usingModelSchema(V1_servicePtrModelSchema), +}); + +const V1_localMappingPropertyModelSchema = createModelSchema( + V1_LocalMappingProperty, + { + multiplicity: object(V1_Multiplicity), + name: primitive(), + type: primitive(), + }, +); + +export const V1_serviceStoreModelSchema = ( + plugins: PureProtocolProcessorPlugin[], +): ModelSchema => + createModelSchema(V1_ServiceStore, { + _type: usingConstantValueSchema(V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE), + description: optional(primitive()), + elements: list( + custom( + (val) => V1_serializeServiceStoreElement(val, plugins), + (val) => V1_deserializeServiceStoreElement(val, plugins), + ), + ), + includedStores: list(primitive()), + name: primitive(), + package: primitive(), + }); + +export const V1_rootServiceStoreClassMappingModelSchema = createModelSchema( + V1_RootServiceStoreClassMapping, + { + _type: usingConstantValueSchema(V1_SERVICE_STORE_MAPPING_PROTOCOL_TYPE), + class: primitive(), + id: optional(primitive()), + localMappingProperties: list( + usingModelSchema(V1_localMappingPropertyModelSchema), + ), + root: primitive(), + servicesMapping: list(usingModelSchema(V1_serviceMappingModelSchema)), + }, +); + +export const V1_serviceStoreConnectionModelSchema = createModelSchema( + V1_ServiceStoreConnection, + { + _type: usingConstantValueSchema(V1_SERVICE_STORE_CONNECTION_PROTOCOL_TYPE), + baseUrl: primitive(), + store: alias('element', optional(primitive())), + name: primitive(), + package: primitive(), + }, +); diff --git a/packages/legend-extension-external-store-service/tsconfig.build.json b/packages/legend-extension-external-store-service/tsconfig.build.json new file mode 100644 index 0000000000..181ddc2c0f --- /dev/null +++ b/packages/legend-extension-external-store-service/tsconfig.build.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "tsBuildInfoFile": "build/prod.tsbuildinfo", + "jsx": "react-jsx" + }, + "exclude": [ + "src/**/__tests__/**/*.ts", + "src/**/__tests__/**/*.tsx", + "src/**/__mocks__/**/*.ts", + "src/**/__mocks__/**/*.tsx" + ], + "references": [{ "path": "./tsconfig.package.json" }] +} diff --git a/packages/legend-extension-external-store-service/tsconfig.json b/packages/legend-extension-external-store-service/tsconfig.json new file mode 100644 index 0000000000..7fa97f9e0e --- /dev/null +++ b/packages/legend-extension-external-store-service/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../scripts/typescript/tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", + "tsBuildInfoFile": "build/dev.tsbuildinfo", + "rootDir": "src", + "jsx": "react-jsxdev" + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.json"], + "references": [ + { "path": "./tsconfig.package.json" }, + { "path": "../legend-graph" }, + { "path": "../legend-studio" }, + { "path": "../legend-shared" }, + { "path": "../legend-model-storage" }, + { "path": "../legend-art" }, + { "path": "../legend-extension-dsl-serializer" } + ] +} diff --git a/packages/legend-extension-external-store-service/tsconfig.package.json b/packages/legend-extension-external-store-service/tsconfig.package.json new file mode 100644 index 0000000000..383b9fddb2 --- /dev/null +++ b/packages/legend-extension-external-store-service/tsconfig.package.json @@ -0,0 +1,9 @@ +{ + "extends": "../../scripts/typescript/tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", + "tsBuildInfoFile": "build/package.tsbuildinfo", + "rootDir": "." + }, + "include": ["package.json"] +} diff --git a/packages/legend-graph/src/DSLMapping_Exports.ts b/packages/legend-graph/src/DSLMapping_Exports.ts index acae52e534..452242335e 100644 --- a/packages/legend-graph/src/DSLMapping_Exports.ts +++ b/packages/legend-graph/src/DSLMapping_Exports.ts @@ -72,4 +72,6 @@ export { V1_EngineRuntime, V1_Runtime, } from './models/protocols/pure/v1/model/packageableElements/runtime/V1_Runtime'; +export { V1_ClassMapping } from './models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping'; +export type { V1_ClassMappingVisitor } from './models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping'; export * from './models/protocols/pure/DSLMapping_PureProtocolProcessorPlugin_Extension'; diff --git a/packages/legend-graph/src/DSLService_Exports.ts b/packages/legend-graph/src/DSLService_Exports.ts index 99e6330056..d881d7bce8 100644 --- a/packages/legend-graph/src/DSLService_Exports.ts +++ b/packages/legend-graph/src/DSLService_Exports.ts @@ -22,4 +22,3 @@ export { } from './models/metamodels/pure/packageableElements/service/ServiceExecution'; export * from './models/metamodels/pure/packageableElements/service/ServiceTest'; export * from './models/metamodels/pure/packageableElements/service/ServiceExecution'; -export { ServiceStore } from './models/metamodels/pure/packageableElements/store/relational/model/ServiceStore'; diff --git a/packages/legend-graph/src/MetaModelConst.ts b/packages/legend-graph/src/MetaModelConst.ts index f40c49acb9..47b9e119f2 100644 --- a/packages/legend-graph/src/MetaModelConst.ts +++ b/packages/legend-graph/src/MetaModelConst.ts @@ -106,7 +106,6 @@ export enum CORE_ELEMENT_PATH { FUNCTION = 'meta::pure::metamodel::function::ConcreteFunctionDefinition', FLAT_DATA = 'meta::flatData::metamodel::FlatData', DATABASE = 'meta::relational::metamodel::Database', - SERVICE_STORE = 'meta::servicestore::metamodel::ServiceStore', MAPPING = 'meta::pure::mapping::Mapping', SERVICE = 'meta::legend::service::metamodel::Service', CONNECTION = 'meta::pure::runtime::PackageableConnection', @@ -183,8 +182,6 @@ export enum CORE_HASH_STRUCTURE { FLAT_DATA_PROPERTY_MAPPING = 'FLAT_DATA_PROPERTY_MAPPING', EMBEDDED_FLAT_DATA_PROPERTY_MAPPING = 'EMBEDDED_FLAT_DATA_PROPERTY_MAPPING', FLAT_DATA_SECTION_POINTER = 'FLAT_DATA_SECTION_POINTER', - // serviceStore - SERVICE_STORE = 'SERVICE_STORE', // database DATABASE = 'DATABASE', DATABASE_SCHEMA = 'DATABASE_SCHEMA', diff --git a/packages/legend-graph/src/__tests__/buildGraph/relational/SimpleRelationalGraphBuildSuccess.test.ts b/packages/legend-graph/src/__tests__/buildGraph/relational/SimpleRelationalGraphBuildSuccess.test.ts index cc8889428a..df0a73a5d7 100644 --- a/packages/legend-graph/src/__tests__/buildGraph/relational/SimpleRelationalGraphBuildSuccess.test.ts +++ b/packages/legend-graph/src/__tests__/buildGraph/relational/SimpleRelationalGraphBuildSuccess.test.ts @@ -41,7 +41,7 @@ beforeEach(async () => { test(unitTest('Relational database is loaded properly'), () => { const graph = graphManagerState.graph; - expect(graph.ownStores).toHaveLength(3); + expect(graph.ownStores).toHaveLength(2); expect(graph.ownDatabases).toHaveLength(2); // db const db = graph.getDatabase('meta::relational::tests::db'); diff --git a/packages/legend-graph/src/__tests__/buildGraph/relational/TEST_DATA__RelationalEntities.ts b/packages/legend-graph/src/__tests__/buildGraph/relational/TEST_DATA__RelationalEntities.ts index c49415a942..076e4251ba 100644 --- a/packages/legend-graph/src/__tests__/buildGraph/relational/TEST_DATA__RelationalEntities.ts +++ b/packages/legend-graph/src/__tests__/buildGraph/relational/TEST_DATA__RelationalEntities.ts @@ -6986,16 +6986,6 @@ export const TEST_DATA__relationalCompleteGraphEntities = [ }, classifierPath: 'meta::relational::metamodel::Database', }, - { - path: 'meta::pure::functions::io::tests::http::testService', - content: { - _type: 'serviceStore', - name: 'testService', - package: 'meta::pure::functions::io::tests::http', - docLink: 'testSeviceConnection', - }, - classifierPath: 'meta::servicestore::metamodel::ServiceStore', - }, { path: 'meta::relational::tests::simpleRelationalMapping', content: { @@ -8433,11 +8423,6 @@ export const TEST_DATA__relationalCompleteGraphEntities = [ elements: ['meta::relational::tests::dbInc'], parserName: 'Relational', }, - { - _type: 'default', - elements: ['meta::pure::functions::io::tests::http::testService'], - parserName: 'ServiceStore', - }, { _type: 'importAware', imports: ['meta::pure::profiles', 'meta::pure::tests::model::simple'], @@ -12611,16 +12596,6 @@ export const TEST_DATA__embeddedRelationalTestData = [ }, classifierPath: 'meta::relational::metamodel::Database', }, - { - path: 'meta::pure::functions::io::tests::http::testService', - content: { - _type: 'serviceStore', - name: 'testService', - package: 'meta::pure::functions::io::tests::http', - docLink: 'testSeviceConnection', - }, - classifierPath: 'meta::servicestore::metamodel::ServiceStore', - }, { path: 'meta::relational::tests::mapping::embedded::model::mapping::testMappingEmbedded', content: { @@ -12915,11 +12890,6 @@ export const TEST_DATA__embeddedRelationalTestData = [ ], parserName: 'Relational', }, - { - _type: 'default', - elements: ['meta::pure::functions::io::tests::http::testService'], - parserName: 'ServiceStore', - }, { _type: 'importAware', imports: ['meta::pure::profiles', 'meta::pure::tests::model::simple'], diff --git a/packages/legend-graph/src/graph/BasicModel.ts b/packages/legend-graph/src/graph/BasicModel.ts index 433cceba95..d073db0311 100644 --- a/packages/legend-graph/src/graph/BasicModel.ts +++ b/packages/legend-graph/src/graph/BasicModel.ts @@ -50,7 +50,6 @@ import { import { Database } from '../models/metamodels/pure/packageableElements/store/relational/model/Database'; import { SectionIndex } from '../models/metamodels/pure/packageableElements/section/SectionIndex'; import type { Section } from '../models/metamodels/pure/packageableElements/section/Section'; -import { ServiceStore } from '../models/metamodels/pure/packageableElements/store/relational/model/ServiceStore'; import { PureGraphExtension } from './PureGraphExtension'; import { PrimitiveType } from '../models/metamodels/pure/packageableElements/domain/PrimitiveType'; import { DataType } from '../models/metamodels/pure/packageableElements/domain/DataType'; @@ -167,7 +166,6 @@ export abstract class BasicModel { ownStores: computed, ownFlatDatas: computed, ownDatabases: computed, - ownServiceStores: computed, ownMappings: computed, ownServices: computed, ownRuntimes: computed, @@ -261,11 +259,6 @@ export abstract class BasicModel { (store: Store): store is Database => store instanceof Database, ); } - get ownServiceStores(): ServiceStore[] { - return Array.from(this.storesIndex.values()).filter( - (store: Store): store is ServiceStore => store instanceof ServiceStore, - ); - } get ownMappings(): Mapping[] { return Array.from(this.mappingsIndex.values()); } diff --git a/packages/legend-graph/src/graph/PureModel.ts b/packages/legend-graph/src/graph/PureModel.ts index 5022c6e622..8fed63b6c7 100644 --- a/packages/legend-graph/src/graph/PureModel.ts +++ b/packages/legend-graph/src/graph/PureModel.ts @@ -56,7 +56,6 @@ import { Measure, Unit, } from '../models/metamodels/pure/packageableElements/domain/Measure'; -import { ServiceStore } from '../models/metamodels/pure/packageableElements/store/relational/model/ServiceStore'; import type { PureGraphPlugin } from './PureGraphPlugin'; /** @@ -301,12 +300,6 @@ export class PureModel extends BasicModel { Database, `Can't find database store '${path}'`, ); - getServiceStore = (path: string): ServiceStore => - guaranteeType( - this.getStore(path), - ServiceStore, - `Can't find service store '${path}'`, - ); getMapping = (path: string): Mapping => guaranteeNonNullable( this.getOwnMapping(path) ?? diff --git a/packages/legend-graph/src/index.ts b/packages/legend-graph/src/index.ts index 21c8cf169a..bc9c07be88 100644 --- a/packages/legend-graph/src/index.ts +++ b/packages/legend-graph/src/index.ts @@ -122,6 +122,7 @@ export { V1_Collection } from './models/protocols/pure/v1/model/valueSpecificati export { V1_Lambda } from './models/protocols/pure/v1/model/valueSpecification/raw/V1_Lambda'; export { V1_Variable } from './models/protocols/pure/v1/model/valueSpecification/V1_Variable'; export { V1_ValueSpecification } from './models/protocols/pure/v1/model/valueSpecification/V1_ValueSpecification'; +export { V1_Multiplicity } from './models/protocols/pure/v1/model/packageableElements/domain/V1_Multiplicity'; // --------------------------------------------- EXECUTION PLAN -------------------------------------------------- diff --git a/packages/legend-graph/src/models/metamodels/pure/packageableElements/PackageableElement.ts b/packages/legend-graph/src/models/metamodels/pure/packageableElements/PackageableElement.ts index e1d20c8903..cd41d4819b 100644 --- a/packages/legend-graph/src/models/metamodels/pure/packageableElements/PackageableElement.ts +++ b/packages/legend-graph/src/models/metamodels/pure/packageableElements/PackageableElement.ts @@ -44,7 +44,6 @@ import type { FileGenerationSpecification } from './fileGeneration/FileGeneratio import type { GenerationSpecification } from './generationSpecification/GenerationSpecification'; import type { Measure } from './domain/Measure'; import type { SectionIndex } from './section/SectionIndex'; -import type { ServiceStore } from './store/relational/model/ServiceStore'; export interface PackageableElementVisitor { visit_PackageableElement(element: PackageableElement): T; @@ -63,7 +62,6 @@ export interface PackageableElementVisitor { visit_FlatData(element: FlatData): T; visit_Database(element: Database): T; - visit_ServiceStore(element: ServiceStore): T; visit_Service(element: Service): T; visit_FileGenerationSpecification(element: FileGenerationSpecification): T; visit_GenerationSpecification(element: GenerationSpecification): T; diff --git a/packages/legend-graph/src/models/metamodels/pure/packageableElements/mapping/SetImplementation.ts b/packages/legend-graph/src/models/metamodels/pure/packageableElements/mapping/SetImplementation.ts index 27f6f09223..87d9bcd9c6 100644 --- a/packages/legend-graph/src/models/metamodels/pure/packageableElements/mapping/SetImplementation.ts +++ b/packages/legend-graph/src/models/metamodels/pure/packageableElements/mapping/SetImplementation.ts @@ -33,8 +33,10 @@ import type { RootRelationalInstanceSetImplementation } from '../store/relationa import type { InferableMappingElementIdValue } from './InferableMappingElementId'; import type { InferableMappingElementRoot } from './InferableMappingElementRoot'; import type { AggregationAwareSetImplementation } from './aggregationAware/AggregationAwareSetImplementation'; +import type { InstanceSetImplementation } from './InstanceSetImplementation'; export interface SetImplementationVisitor { + visit_SetImplementation(setImplementation: InstanceSetImplementation): T; visit_OperationSetImplementation( setImplementation: OperationSetImplementation, ): T; diff --git a/packages/legend-graph/src/models/protocols/pure/DSLMapping_PureProtocolProcessorPlugin_Extension.ts b/packages/legend-graph/src/models/protocols/pure/DSLMapping_PureProtocolProcessorPlugin_Extension.ts index 658553c15d..695f99058a 100644 --- a/packages/legend-graph/src/models/protocols/pure/DSLMapping_PureProtocolProcessorPlugin_Extension.ts +++ b/packages/legend-graph/src/models/protocols/pure/DSLMapping_PureProtocolProcessorPlugin_Extension.ts @@ -16,13 +16,41 @@ import type { PlainObject } from '@finos/legend-shared'; import type { Connection } from '../../metamodels/pure/packageableElements/connection/Connection'; +import type { Mapping } from '../../metamodels/pure/packageableElements/mapping/Mapping'; +import type { InstanceSetImplementation } from '../../metamodels/pure/packageableElements/mapping/InstanceSetImplementation'; import type { PureProtocolProcessorPlugin } from './PureProtocolProcessorPlugin'; import type { V1_Connection } from '../pure/v1/model/packageableElements/connection/V1_Connection'; import type { V1_GraphTransformerContext } from './v1/transformation/pureGraph/from/V1_GraphTransformerContext'; +import type { V1_ClassMapping } from '../pure/v1/model/packageableElements/mapping/V1_ClassMapping'; import type { V1_GraphBuilderContext } from './v1/transformation/pureGraph/to/V1_GraphBuilderContext'; import type { Store } from '../../metamodels/pure/packageableElements/store/Store'; import type { PackageableElementReference } from '../../metamodels/pure/packageableElements/PackageableElementReference'; +export type V1_ClassMappingFirstPassBuilder = ( + classMapping: V1_ClassMapping, + context: V1_GraphBuilderContext, + parent: Mapping, +) => InstanceSetImplementation | undefined; + +export type V1_ClassMappingSecondPassBuilder = ( + classMapping: V1_ClassMapping, + context: V1_GraphBuilderContext, + parent: Mapping, +) => void; + +export type V1_ClassMappingTransformer = ( + setImplementation: InstanceSetImplementation, + context: V1_GraphTransformerContext, +) => V1_ClassMapping | undefined; + +export type V1_ClassMappingSerializer = ( + value: V1_ClassMapping, +) => V1_ClassMapping | undefined; + +export type V1_ClassMappingDeserializer = ( + json: PlainObject, +) => V1_ClassMapping | undefined; + export type V1_ConnectionBuilder = ( connection: V1_Connection, context: V1_GraphBuilderContext, @@ -44,6 +72,16 @@ export type V1_ConnectionProtocolDeserializer = ( export interface DSLMapping_PureProtocolProcessorPlugin_Extension extends PureProtocolProcessorPlugin { + V1_getExtraClassMappingFirstPassBuilders?(): V1_ClassMappingFirstPassBuilder[]; + + V1_getExtraClassMappingSecondPassBuilders?(): V1_ClassMappingSecondPassBuilder[]; + + V1_getExtraClassMappingTransformers?(): V1_ClassMappingTransformer[]; + + V1_getExtraClassMappingSerializers?(): V1_ClassMappingSerializer[]; + + V1_getExtraClassMappingDeserializers?(): V1_ClassMappingDeserializer[]; + V1_getExtraConnectionBuilders?(): V1_ConnectionBuilder[]; V1_getExtraConnectionTransformers?(): V1_ConnectionTransformer[]; diff --git a/packages/legend-graph/src/models/protocols/pure/PureProtocolProcessorPlugin.ts b/packages/legend-graph/src/models/protocols/pure/PureProtocolProcessorPlugin.ts index 3bc6f869a9..8065e7b3f2 100644 --- a/packages/legend-graph/src/models/protocols/pure/PureProtocolProcessorPlugin.ts +++ b/packages/legend-graph/src/models/protocols/pure/PureProtocolProcessorPlugin.ts @@ -41,10 +41,12 @@ export type V1_ElementTransformer = ( export type V1_ElementProtocolSerializer = ( protocol: V1_PackageableElement, + plugins: PureProtocolProcessorPlugin[], ) => PlainObject | undefined; export type V1_ElementProtocolDeserializer = ( protocol: PlainObject, + plugins: PureProtocolProcessorPlugin[], ) => V1_PackageableElement | undefined; export type V1_FunctionExpressionBuilder = ( diff --git a/packages/legend-graph/src/models/protocols/pure/v1/V1_PureGraphManager.ts b/packages/legend-graph/src/models/protocols/pure/v1/V1_PureGraphManager.ts index 1750b1061c..37ddb7e097 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/V1_PureGraphManager.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/V1_PureGraphManager.ts @@ -154,7 +154,6 @@ import { import { V1_transformRelationalDatabaseConnection } from './transformation/pureGraph/from/V1_ConnectionTransformer'; import { V1_FlatData } from './model/packageableElements/store/flatData/model/V1_FlatData'; import { V1_Database } from './model/packageableElements/store/relational/model/V1_Database'; -import { V1_ServiceStore } from './model/packageableElements/store/relational/V1_ServiceStore'; import type { V1_Multiplicity } from './model/packageableElements/domain/V1_Multiplicity'; import type { V1_RawVariable } from './model/rawValueSpecification/V1_RawVariable'; import { V1_setupDatabaseSerialization } from './transformation/pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper'; @@ -2280,8 +2279,6 @@ export class V1_PureGraphManager extends AbstractPureGraphManager { return CORE_ELEMENT_PATH.FLAT_DATA; } else if (protocol instanceof V1_Database) { return CORE_ELEMENT_PATH.DATABASE; - } else if (protocol instanceof V1_ServiceStore) { - return CORE_ELEMENT_PATH.SERVICE_STORE; } else if (protocol instanceof V1_Service) { return CORE_ELEMENT_PATH.SERVICE; } else if (protocol instanceof V1_FileGenerationSpecification) { diff --git a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/V1_PackageableElement.ts b/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/V1_PackageableElement.ts index 34dcfe028e..c40bc301b8 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/V1_PackageableElement.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/V1_PackageableElement.ts @@ -35,7 +35,6 @@ import type { V1_FileGenerationSpecification } from './fileGeneration/V1_FileGen import type { V1_GenerationSpecification } from './generationSpecification/V1_GenerationSpecification'; import type { V1_Measure } from './domain/V1_Measure'; import type { V1_SectionIndex } from './section/V1_SectionIndex'; -import type { V1_ServiceStore } from './store/relational/V1_ServiceStore'; export interface V1_PackageableElementVisitor { visit_PackageableElement(element: V1_PackageableElement): T; @@ -52,7 +51,6 @@ export interface V1_PackageableElementVisitor { visit_FlatData(element: V1_FlatData): T; visit_Database(element: V1_Database): T; - visit_ServiceStore(element: V1_ServiceStore): T; visit_Service(element: V1_Service): T; visit_GenerationSpecification(element: V1_GenerationSpecification): T; visit_FileGeneration(element: V1_FileGenerationSpecification): T; diff --git a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping.ts b/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping.ts index 9c941fd254..2784c42ec5 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/model/packageableElements/mapping/V1_ClassMapping.ts @@ -27,6 +27,7 @@ import type { V1_RootFlatDataClassMapping } from '../../../model/packageableElem /* @MARKER: NEW CLASS MAPPING TYPE SUPPORT --- consider adding class mapping type handler here whenever support for a new one is added to the app */ export interface V1_ClassMappingVisitor { + visit_ClassMapping(classMapping: V1_ClassMapping): T; visit_OperationClassMapping(classMapping: V1_OperationClassMapping): T; visit_PureInstanceClassMapping(classMapping: V1_PureInstanceClassMapping): T; visit_RootFlatDataClassMapping(classMapping: V1_RootFlatDataClassMapping): T; diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_MappingTransformer.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_MappingTransformer.ts index 1fc8fb51c4..808c1b01a5 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_MappingTransformer.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_MappingTransformer.ts @@ -139,6 +139,8 @@ import { V1_RelationalInputData } from '../../../model/packageableElements/store import { SOURCE_INFORMATION_KEY } from '../../../../../../../MetaModelConst'; import type { V1_GraphTransformerContext } from './V1_GraphTransformerContext'; import { toJS } from 'mobx'; +import type { DSLMapping_PureProtocolProcessorPlugin_Extension } from '../../../../DSLMapping_PureProtocolProcessorPlugin_Extension'; +import type { InstanceSetImplementation } from '../../../../../../metamodels/pure/packageableElements/mapping/InstanceSetImplementation'; export const V1_transformPropertyReference = ( element: PropertyReference, @@ -1008,6 +1010,27 @@ export class V1_SetImplementationTransformer this.context = context; } + visit_SetImplementation( + setImplementation: InstanceSetImplementation, + ): V1_ClassMapping | undefined { + const extraClassMappingTransformers = this.context.plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_PureProtocolProcessorPlugin_Extension + ).V1_getExtraClassMappingTransformers?.() ?? [], + ); + for (const transformer of extraClassMappingTransformers) { + const classMapping = transformer(setImplementation, this.context); + if (classMapping) { + return classMapping; + } + } + throw new UnsupportedOperationError( + `Can't transform class mapping: no compatible transformer available from plugins`, + setImplementation, + ); + } + visit_OperationSetImplementation( setImplementation: OperationSetImplementation, ): V1_ClassMapping | undefined { diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_PackageableElementTransformer.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_PackageableElementTransformer.ts index 1352008428..8a2104fc9b 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_PackageableElementTransformer.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/from/V1_PackageableElementTransformer.ts @@ -27,7 +27,6 @@ import type { Association } from '../../../../../../metamodels/pure/packageableE import type { ConcreteFunctionDefinition } from '../../../../../../metamodels/pure/packageableElements/domain/ConcreteFunctionDefinition'; import type { FlatData } from '../../../../../../metamodels/pure/packageableElements/store/flatData/model/FlatData'; import type { Database } from '../../../../../../metamodels/pure/packageableElements/store/relational/model/Database'; -import type { ServiceStore } from '../../../../../../metamodels/pure/packageableElements/store/relational/model/ServiceStore'; import type { Mapping } from '../../../../../../metamodels/pure/packageableElements/mapping/Mapping'; import type { Service } from '../../../../../../metamodels/pure/packageableElements/service/Service'; import type { PackageableRuntime } from '../../../../../../metamodels/pure/packageableElements/runtime/PackageableRuntime'; @@ -52,7 +51,6 @@ import { V1_transformGenerationSpecification, } from './V1_GenerationSpecificationTransformer'; import { V1_transformFlatData } from './V1_FlatDataTransformer'; -import { V1_transformServiceStore } from './V1_ServiceStoreTransformer'; import { V1_transformDatabase } from './V1_DatabaseTransformer'; import { V1_transformMapping } from './V1_MappingTransformer'; import { V1_transformService } from './V1_ServiceTransformer'; @@ -143,10 +141,6 @@ export class V1_PackageableElementTransformer return V1_transformDatabase(element, this.context); } - visit_ServiceStore(element: ServiceStore): V1_PackageableElement { - return V1_transformServiceStore(element); - } - visit_Mapping(element: Mapping): V1_PackageableElement { return V1_transformMapping(element, this.context); } diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingFirstPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingFirstPassBuilder.ts index a28705e185..df782ba405 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingFirstPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingFirstPassBuilder.ts @@ -30,7 +30,10 @@ import { FlatDataInstanceSetImplementation } from '../../../../../../metamodels/ import { RootRelationalInstanceSetImplementation } from '../../../../../../metamodels/pure/packageableElements/store/relational/mapping/RootRelationalInstanceSetImplementation'; import { InferableMappingElementRootExplicitValue } from '../../../../../../metamodels/pure/packageableElements/mapping/InferableMappingElementRoot'; import type { V1_GraphBuilderContext } from '../../../transformation/pureGraph/to/V1_GraphBuilderContext'; -import type { V1_ClassMappingVisitor } from '../../../model/packageableElements/mapping/V1_ClassMapping'; +import type { + V1_ClassMappingVisitor, + V1_ClassMapping, +} from '../../../model/packageableElements/mapping/V1_ClassMapping'; import type { V1_OperationClassMapping } from '../../../model/packageableElements/mapping/V1_OperationClassMapping'; import type { V1_PureInstanceClassMapping } from '../../../model/packageableElements/store/modelToModel/mapping/V1_PureInstanceClassMapping'; import type { V1_RelationalClassMapping } from '../../../model/packageableElements/store/relational/mapping/V1_RelationalClassMapping'; @@ -44,6 +47,7 @@ import { V1_buildAggregateContainer } from './helpers/V1_AggregationAwareClassMa import { V1_resolvePathsInRawLambda } from './helpers/V1_ValueSpecificationPathResolver'; import { V1_buildRelationalMappingFilter } from './helpers/V1_RelationalClassMappingBuilderHelper'; import { toOptionalPackageableElementReference } from '../../../../../../metamodels/pure/packageableElements/PackageableElementReference'; +import type { DSLMapping_PureProtocolProcessorPlugin_Extension } from '../../../../DSLMapping_PureProtocolProcessorPlugin_Extension'; export class V1_ProtocolToMetaModelClassMappingFirstPassBuilder implements V1_ClassMappingVisitor @@ -56,6 +60,29 @@ export class V1_ProtocolToMetaModelClassMappingFirstPassBuilder this.parent = parent; } + visit_ClassMapping(classMapping: V1_ClassMapping): SetImplementation { + const extraClassMappingBuilders = this.context.extensions.plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_PureProtocolProcessorPlugin_Extension + ).V1_getExtraClassMappingFirstPassBuilders?.() ?? [], + ); + for (const builder of extraClassMappingBuilders) { + const extraClassMapping = builder( + classMapping, + this.context, + this.parent, + ); + if (extraClassMapping) { + return extraClassMapping; + } + } + throw new UnsupportedOperationError( + `Can't build new class mapping: no compatible builder available from plugins`, + classMapping, + ); + } + visit_OperationClassMapping( classMapping: V1_OperationClassMapping, ): SetImplementation { diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingSecondPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingSecondPassBuilder.ts index dbe60b2e9d..94bc6f3fc7 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingSecondPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelClassMappingSecondPassBuilder.ts @@ -43,7 +43,10 @@ import { V1_buildRelationalClassMapping, V1_buildRelationalPrimaryKey, } from './helpers/V1_RelationalClassMappingBuilderHelper'; -import type { V1_ClassMappingVisitor } from '../../../model/packageableElements/mapping/V1_ClassMapping'; +import type { + V1_ClassMappingVisitor, + V1_ClassMapping, +} from '../../../model/packageableElements/mapping/V1_ClassMapping'; import type { V1_OperationClassMapping } from '../../../model/packageableElements/mapping/V1_OperationClassMapping'; import type { V1_PureInstanceClassMapping } from '../../../model/packageableElements/store/modelToModel/mapping/V1_PureInstanceClassMapping'; import type { V1_RelationalClassMapping } from '../../../model/packageableElements/store/relational/mapping/V1_RelationalClassMapping'; @@ -61,6 +64,7 @@ import { getAllEnumerationMappings, getOwnClassMappingById, } from '../../../../../../../helpers/MappingHelper'; +import type { DSLMapping_PureProtocolProcessorPlugin_Extension } from '../../../../DSLMapping_PureProtocolProcessorPlugin_Extension'; export class V1_ProtocolToMetaModelClassMappingSecondPassBuilder implements V1_ClassMappingVisitor @@ -73,6 +77,18 @@ export class V1_ProtocolToMetaModelClassMappingSecondPassBuilder this.parent = parent; } + visit_ClassMapping(classMapping: V1_ClassMapping): void { + const extraClassMappingBuilders = this.context.extensions.plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_PureProtocolProcessorPlugin_Extension + ).V1_getExtraClassMappingSecondPassBuilders?.() ?? [], + ); + for (const builder of extraClassMappingBuilders) { + builder(classMapping, this.context, this.parent); + } + } + visit_OperationClassMapping(classMapping: V1_OperationClassMapping): void { assertNonEmptyString( classMapping.class, diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFifthPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFifthPassBuilder.ts index 20c8effd4a..72ad90732f 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFifthPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFifthPassBuilder.ts @@ -40,7 +40,6 @@ import type { V1_GenerationSpecification } from '../../../model/packageableEleme import type { V1_Measure } from '../../../model/packageableElements/domain/V1_Measure'; import { V1_buildDatabaseSchemaViewsSecondPass } from './helpers/V1_DatabaseBuilderHelper'; import type { V1_SectionIndex } from '../../../model/packageableElements/section/V1_SectionIndex'; -import type { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; export class V1_ProtocolToMetaModelGraphFifthPassBuilder implements V1_PackageableElementVisitor @@ -107,12 +106,6 @@ export class V1_ProtocolToMetaModelGraphFifthPassBuilder ); } - visit_ServiceStore(element: V1_ServiceStore): void { - this.context.graph.getServiceStore( - this.context.graph.buildPath(element.package, element.name), - ); - } - visit_Mapping(element: V1_Mapping): void { throw new UnsupportedOperationError(); } diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFirstPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFirstPassBuilder.ts index 645df5c3d0..e7d4b0ac07 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFirstPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFirstPassBuilder.ts @@ -28,7 +28,6 @@ import { Association } from '../../../../../../metamodels/pure/packageableElemen import { ConcreteFunctionDefinition } from '../../../../../../metamodels/pure/packageableElements/domain/ConcreteFunctionDefinition'; import { FlatData } from '../../../../../../metamodels/pure/packageableElements/store/flatData/model/FlatData'; import { Database } from '../../../../../../metamodels/pure/packageableElements/store/relational/model/Database'; -import { ServiceStore } from '../../../../../../metamodels/pure/packageableElements/store/relational/model/ServiceStore'; import { Mapping } from '../../../../../../metamodels/pure/packageableElements/mapping/Mapping'; import { Service } from '../../../../../../metamodels/pure/packageableElements/service/Service'; import { FileGenerationSpecification } from '../../../../../../metamodels/pure/packageableElements/fileGeneration/FileGenerationSpecification'; @@ -57,7 +56,6 @@ import type { V1_PackageableConnection } from '../../../model/packageableElement import type { V1_FileGenerationSpecification } from '../../../model/packageableElements/fileGeneration/V1_FileGenerationSpecification'; import type { V1_Measure } from '../../../model/packageableElements/domain/V1_Measure'; import type { V1_SectionIndex } from '../../../model/packageableElements/section/V1_SectionIndex'; -import type { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; export class V1_ProtocolToMetaModelGraphFirstPassBuilder implements V1_PackageableElementVisitor @@ -308,31 +306,6 @@ export class V1_ProtocolToMetaModelGraphFirstPassBuilder return database; } - visit_ServiceStore(element: V1_ServiceStore): PackageableElement { - assertNonEmptyString( - element.package, - `Service store 'package' field is missing or empty`, - ); - assertNonEmptyString( - element.name, - `Service store 'name' field is missing or empty`, - ); - const serviceStore = new ServiceStore(element.name); - const path = this.context.currentSubGraph.buildPath( - element.package, - element.name, - ); - assertTrue( - !this.context.graph.getNullableElement(path), - `Element '${path}' already exists`, - ); - this.context.currentSubGraph - .getOrCreatePackage(element.package) - .addElement(serviceStore); - this.context.currentSubGraph.setOwnStore(path, serviceStore); - return serviceStore; - } - visit_Mapping(element: V1_Mapping): PackageableElement { assertNonEmptyString( element.package, diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFourthPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFourthPassBuilder.ts index 786a85a97e..658713adf8 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFourthPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphFourthPassBuilder.ts @@ -44,7 +44,6 @@ import { V1_buildDatabaseFilter, } from './helpers/V1_DatabaseBuilderHelper'; import type { V1_SectionIndex } from '../../../model/packageableElements/section/V1_SectionIndex'; -import type { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; import { V1_buildAssociationMapping } from './helpers/V1_AssociationMappingHelper'; export class V1_ProtocolToMetaModelGraphFourthPassBuilder @@ -108,12 +107,6 @@ export class V1_ProtocolToMetaModelGraphFourthPassBuilder ); } - visit_ServiceStore(element: V1_ServiceStore): void { - this.context.graph.getServiceStore( - this.context.graph.buildPath(element.package, element.name), - ); - } - visit_Mapping(element: V1_Mapping): void { const path = this.context.graph.buildPath(element.package, element.name); const mapping = this.context.graph.getMapping(path); diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphSecondPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphSecondPassBuilder.ts index cd7fcaa617..2c6b93ba39 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphSecondPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphSecondPassBuilder.ts @@ -73,7 +73,6 @@ import { import type { V1_Measure } from '../../../model/packageableElements/domain/V1_Measure'; import type { V1_SectionIndex } from '../../../model/packageableElements/section/V1_SectionIndex'; import { V1_buildSection } from '../../../transformation/pureGraph/to/helpers/V1_SectionBuilderHelper'; -import type { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; export class V1_ProtocolToMetaModelGraphSecondPassBuilder implements V1_PackageableElementVisitor @@ -216,18 +215,6 @@ export class V1_ProtocolToMetaModelGraphSecondPassBuilder ); } - visit_ServiceStore(element: V1_ServiceStore): void { - assertNonEmptyString( - element.docLink, - `Service store 'docLink' field is missing`, - ); - const serviceStore = this.context.graph.getServiceStore( - this.context.graph.buildPath(element.package, element.name), - ); - // TODO includedStores - serviceStore.docLink = element.docLink; - } - visit_Mapping(element: V1_Mapping): void { const mapping = this.context.graph.getMapping( this.context.graph.buildPath(element.package, element.name), diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphThirdPassBuilder.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphThirdPassBuilder.ts index 5359d5506e..d8c6f2e6bd 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphThirdPassBuilder.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureGraph/to/V1_ProtocolToMetaModelGraphThirdPassBuilder.ts @@ -50,7 +50,6 @@ import type { V1_GenerationSpecification } from '../../../model/packageableEleme import type { V1_Measure } from '../../../model/packageableElements/domain/V1_Measure'; import { V1_buildDatabaseSchemaViewsFirstPass } from '../../../transformation/pureGraph/to/helpers/V1_DatabaseBuilderHelper'; import type { V1_SectionIndex } from '../../../model/packageableElements/section/V1_SectionIndex'; -import type { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; import { GraphBuilderError } from '../../../../../../../graphManager/GraphManagerUtils'; export class V1_ProtocolToMetaModelGraphThirdPassBuilder @@ -157,12 +156,6 @@ export class V1_ProtocolToMetaModelGraphThirdPassBuilder ); } - visit_ServiceStore(element: V1_ServiceStore): void { - this.context.graph.getServiceStore( - this.context.graph.buildPath(element.package, element.name), - ); - } - visit_Mapping(element: V1_Mapping): void { const path = this.context.graph.buildPath(element.package, element.name); const mapping = this.context.graph.getMapping(path); diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/V1_PackageableElementSerialization.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/V1_PackageableElementSerialization.ts index b496cc6734..e5eee87f26 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/V1_PackageableElementSerialization.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/V1_PackageableElementSerialization.ts @@ -36,12 +36,9 @@ import type { V1_SectionIndex } from '../../model/packageableElements/section/V1 import type { V1_Service } from '../../model/packageableElements/service/V1_Service'; import type { V1_FlatData } from '../../model/packageableElements/store/flatData/model/V1_FlatData'; import type { V1_Database } from '../../model/packageableElements/store/relational/model/V1_Database'; -import type { V1_ServiceStore } from '../../model/packageableElements/store/relational/V1_ServiceStore'; import { V1_flatDataModelSchema, V1_FLAT_DATA_ELEMENT_PROTOCOL_TYPE, - V1_serviceStoreModelSchema, - V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE, } from './serializationHelpers/V1_StoreSerializationHelper'; import { V1_mappingModelSchema, @@ -111,7 +108,7 @@ export class V1_PackageableElementSerializer elementProtocol: V1_PackageableElement, ): PlainObject { for (const serializer of this.extraElementProtocolSerializers) { - const elementProtocolJson = serializer(elementProtocol); + const elementProtocolJson = serializer(elementProtocol, this.plugins); if (elementProtocolJson) { return elementProtocolJson; } @@ -159,14 +156,8 @@ export class V1_PackageableElementSerializer return serialize(V1_databaseModelSchema, element); } - visit_ServiceStore( - element: V1_ServiceStore, - ): PlainObject { - return serialize(V1_serviceStoreModelSchema, element); - } - visit_Mapping(element: V1_Mapping): PlainObject { - return serialize(V1_mappingModelSchema, element); + return serialize(V1_mappingModelSchema(this.plugins), element); } visit_Service(element: V1_Service): PlainObject { @@ -231,10 +222,8 @@ export const V1_deserializePackageableElement = ( return deserialize(V1_flatDataModelSchema, json); case V1_DATABASE_ELEMENT_PROTOCOL_TYPE: return deserialize(V1_databaseModelSchema, json); - case V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE: - return deserialize(V1_serviceStoreModelSchema, json); case V1_MAPPING_ELEMENT_PROTOCOL_TYPE: - return deserialize(V1_mappingModelSchema, json); + return deserialize(V1_mappingModelSchema(plugins), json); case V1_SERVICE_ELEMENT_PROTOCOL_TYPE: return deserialize(V1_servicedModelSchema, json); case V1_PACKAGEABLE_CONNECTION_ELEMENT_PROTOCOL_TYPE: @@ -249,7 +238,7 @@ export const V1_deserializePackageableElement = ( return deserialize(V1_sectionIndexModelSchema, json); default: { for (const deserializer of extraElementProtocolDeserializers) { - const elementProtocol = deserializer(json); + const elementProtocol = deserializer(json, plugins); if (elementProtocol) { return elementProtocol; } diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_MappingSerializationHelper.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_MappingSerializationHelper.ts index f34173621d..9206382ca1 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_MappingSerializationHelper.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_MappingSerializationHelper.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { ModelSchema } from 'serializr'; import { createModelSchema, list, @@ -95,6 +96,8 @@ import type { V1_AbstractFlatDataPropertyMapping } from '../../../model/packagea import { V1_XStorePropertyMapping } from '../../../model/packageableElements/mapping/xStore/V1_XStorePropertyMapping'; import { V1_XStoreAssociationMapping } from '../../../model/packageableElements/mapping/xStore/V1_XStoreAssociationMapping'; import { V1_RelationalInputData } from '../../../model/packageableElements/store/relational/mapping/V1_RelationalInputData'; +import type { DSLMapping_PureProtocolProcessorPlugin_Extension } from '../../../../DSLMapping_PureProtocolProcessorPlugin_Extension'; +import type { PureProtocolProcessorPlugin } from '../../../../PureProtocolProcessorPlugin'; enum V1_ClassMappingType { OPERATION = 'operation', @@ -559,7 +562,8 @@ const aggregationAwareClassMappingModelSchema = createModelSchema( function V1_serializeClassMapping( value: V1_ClassMapping, -): V1_ClassMapping | typeof SKIP { + plugins?: PureProtocolProcessorPlugin[] | undefined, +): V1_ClassMapping { if (value instanceof V1_OperationClassMapping) { return serialize(operationClassMappingModelSchema, value); } else if (value instanceof V1_PureInstanceClassMapping) { @@ -573,12 +577,30 @@ function V1_serializeClassMapping( } else if (value instanceof V1_AggregationAwareClassMapping) { return serialize(aggregationAwareClassMappingModelSchema, value); } - return SKIP; + if (plugins !== undefined) { + const extraClassMappingSerializers = plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_PureProtocolProcessorPlugin_Extension + ).V1_getExtraClassMappingSerializers?.() ?? [], + ); + for (const serializer of extraClassMappingSerializers) { + const json = serializer(value); + if (json) { + return json; + } + } + } + throw new UnsupportedOperationError( + `Can't serialize class mapping: no compatible serializer available from plugins`, + value, + ); } function V1_deserializeClassMapping( json: PlainObject, -): V1_ClassMapping | typeof SKIP { + plugins?: PureProtocolProcessorPlugin[], +): V1_ClassMapping { switch (json._type) { case V1_ClassMappingType.OPERATION: return deserialize(operationClassMappingModelSchema, json); @@ -592,8 +614,25 @@ function V1_deserializeClassMapping( return deserialize(relationalClassMappingModelSchema, json); case V1_ClassMappingType.AGGREGATION_AWARE: return deserialize(aggregationAwareClassMappingModelSchema, json); - default: - return SKIP; + default: { + if (plugins !== undefined) { + const extraClassMappingDeserializers = plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_PureProtocolProcessorPlugin_Extension + ).V1_getExtraClassMappingDeserializers?.() ?? [], + ); + for (const deserializer of extraClassMappingDeserializers) { + const protocol = deserializer(json); + if (protocol) { + return protocol; + } + } + } + throw new UnsupportedOperationError( + `Can't deserialize class mapping of type '${json._type}': no compatible deserializer available from plugins`, + ); + } } } @@ -946,32 +985,47 @@ const V1_mappingIncludeModelSchema = createModelSchema(V1_MappingInclude, { targetDatabasePath: optional(primitive()), }); -export const V1_mappingModelSchema = createModelSchema(V1_Mapping, { - _type: usingConstantValueSchema(V1_MAPPING_ELEMENT_PROTOCOL_TYPE), - associationMappings: custom( - (values) => - serializeArray( - values, - (value) => V1_serializeAssociationMapping(value), - true, - ), - (values) => - deserializeArray( - values, - (val: PlainObject) => - V1_deserializeAssociationMapping(val), - false, +export const V1_mappingModelSchema = ( + plugins?: PureProtocolProcessorPlugin[], +): ModelSchema => + createModelSchema(V1_Mapping, { + _type: usingConstantValueSchema(V1_MAPPING_ELEMENT_PROTOCOL_TYPE), + associationMappings: custom( + (values) => + serializeArray( + values, + (value) => V1_serializeAssociationMapping(value), + true, + ), + (values) => + deserializeArray( + values, + (val: PlainObject) => + V1_deserializeAssociationMapping(val), + false, + ), + ), + classMappings: list( + custom( + (val) => { + if (plugins !== undefined) { + return V1_serializeClassMapping(val, plugins); + } + return V1_serializeClassMapping(val); + }, + (val) => { + if (plugins !== undefined) { + return V1_deserializeClassMapping(val, plugins); + } + return V1_deserializeClassMapping(val); + }, ), - ), - classMappings: list( - custom( - (val) => V1_serializeClassMapping(val), - (val) => V1_deserializeClassMapping(val), ), - ), - enumerationMappings: list(usingModelSchema(V1_enumerationMappingModelSchema)), - includedMappings: list(usingModelSchema(V1_mappingIncludeModelSchema)), - name: primitive(), - package: primitive(), - tests: list(usingModelSchema(V1_mappingTestModelSchema)), -}); + enumerationMappings: list( + usingModelSchema(V1_enumerationMappingModelSchema), + ), + includedMappings: list(usingModelSchema(V1_mappingIncludeModelSchema)), + name: primitive(), + package: primitive(), + tests: list(usingModelSchema(V1_mappingTestModelSchema)), + }); diff --git a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_StoreSerializationHelper.ts b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_StoreSerializationHelper.ts index 0cc67a7847..4f2b1169a9 100644 --- a/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_StoreSerializationHelper.ts +++ b/packages/legend-graph/src/models/protocols/pure/v1/transformation/pureProtocol/serializationHelpers/V1_StoreSerializationHelper.ts @@ -32,7 +32,6 @@ import { serializeArray, usingModelSchema, } from '@finos/legend-shared'; -import { V1_ServiceStore } from '../../../model/packageableElements/store/relational/V1_ServiceStore'; import { V1_FlatData } from '../../../model/packageableElements/store/flatData/model/V1_FlatData'; import { V1_FlatDataProperty } from '../../../model/packageableElements/store/flatData/model/V1_FlatDataProperty'; import type { V1_FlatDataDataType } from '../../../model/packageableElements/store/flatData/model/V1_FlatDataDataType'; @@ -52,18 +51,6 @@ import { } from '../../../model/packageableElements/store/flatData/model/V1_FlatDataDataType'; import { V1_FlatDataSection } from '../../../model/packageableElements/store/flatData/model/V1_FlatDataSection'; -// ------------------------------------------ Service Store ------------------------------------------ - -export const V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE = 'serviceStore'; - -export const V1_serviceStoreModelSchema = createModelSchema(V1_ServiceStore, { - _type: usingConstantValueSchema(V1_SERVICE_STORE_ELEMENT_PROTOCOL_TYPE), - docLink: primitive(), - includedStores: list(primitive()), - name: primitive(), - package: primitive(), -}); - // ------------------------------------------ Flat Data ------------------------------------------ export const V1_FLAT_DATA_ELEMENT_PROTOCOL_TYPE = 'flatData'; diff --git a/packages/legend-manual-tests/package.json b/packages/legend-manual-tests/package.json index e823165d2d..8c3dbe1ee7 100644 --- a/packages/legend-manual-tests/package.json +++ b/packages/legend-manual-tests/package.json @@ -26,6 +26,7 @@ "@finos/legend-extension-dsl-diagram": "workspace:*", "@finos/legend-extension-dsl-serializer": "workspace:*", "@finos/legend-extension-dsl-text": "workspace:*", + "@finos/legend-extension-external-store-service": "workspace:*", "@finos/legend-graph": "workspace:*", "@finos/legend-shared": "workspace:*" }, diff --git a/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/RoundtripGrammar.test.ts b/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/RoundtripGrammar.test.ts index 806280aaaa..e050702f7e 100644 --- a/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/RoundtripGrammar.test.ts +++ b/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/RoundtripGrammar.test.ts @@ -57,6 +57,7 @@ import { DSLText_GraphPreset } from '@finos/legend-extension-dsl-text'; import { DSLDiagram_GraphPreset } from '@finos/legend-extension-dsl-diagram'; import { DSLSerializer_GraphPreset } from '@finos/legend-extension-dsl-serializer'; import { DSLDataSpace_GraphPreset } from '@finos/legend-extension-dsl-data-space'; +import { ESService_GraphPreset } from '@finos/legend-extension-external-store-service'; const engineConfig = JSON.parse( fs.readFileSync(resolve(__dirname, '../../../engine-config.json'), { @@ -78,6 +79,7 @@ enum ROUNTRIP_TEST_PHASES { const SKIP = Symbol('SKIP GRAMMAR ROUNDTRIP TEST'); const EXCLUSIONS: { [key: string]: ROUNTRIP_TEST_PHASES[] | typeof SKIP } = { + 'ESService-basic.pure': SKIP, //Needs https://github.com/finos/legend-engine/pull/417 to be merged // post processor mismatch between engine (undefined) vs studio ([]) 'relational-connection.pure': [ROUNTRIP_TEST_PHASES.PROTOCOL_ROUNDTRIP], @@ -139,6 +141,7 @@ const checkGrammarRoundtrip = async ( new DSLDiagram_GraphPreset(), new DSLSerializer_GraphPreset(), new DSLDataSpace_GraphPreset(), + new ESService_GraphPreset(), ]); pluginManager.install(); const graphManagerState = TEST__getTestGraphManagerState(pluginManager); diff --git a/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/cases/ESService-basic.pure b/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/cases/ESService-basic.pure new file mode 100644 index 0000000000..bdf0d7b5c9 --- /dev/null +++ b/packages/legend-manual-tests/src/__tests__/roundtrip-grammar/cases/ESService-basic.pure @@ -0,0 +1,109 @@ +###ExternalFormat +SchemaSet test::tradeSchema +{ + format: FlatData; + schemas: [ + { + content: 'section trade: DelimitedWithHeadings\n{\n scope.untilEof;\n delimiter: \',\';\n nullString: \'\';\n\n Record\n {\n Product : STRING;\n Quantity : INTEGER;\n \'Trade Time\' : DATETIME;\n Price : DECIMAL;\n \'Price Ccy\' : STRING;\n \'Settlement Ccy\' : STRING(optional);\n \'Settlement Rate\' : DECIMAL(optional);\n \'Settlement Date\' : DATE;\n \'Confirmed At\' : DATETIME(optional);\n \'Expiry Date\' : DATE(optional);\n \'Executions\' : INTEGER(optional);\n }\n}'; + } + ]; +} + +Binding test::gen::TestBinding +{ + schemaSet: test::tradeSchema; + contentType: 'application/x.flatdata'; + modelIncludes: [ + test::gen::Trade + ]; +} + + +###Pure +Class test::gen::Trade +{ + product: String[1]; + quantity: Integer[1]; + tradeTime: DateTime[1]; + price: Float[1]; + priceCcy: String[1]; + settlementCcy: String[0..1]; + settlementRate: Float[0..1]; + settlementDate: StrictDate[1]; + confirmedAt: DateTime[0..1]; + expiryDate: StrictDate[0..1]; + executions: Integer[0..1]; +} + + +###ServiceStore +ServiceStore test::testServiceStoreCompilationWithSingleService1 +( + Service TestService + ( + path : '/testService'; + method : GET; + parameters : + ( + serializationFormat : String ( location = query ) + ); + response : [test::gen::Trade <- test::gen::TestBinding]; + security : []; + ) +) + +ServiceStore test::ServiceStore1 +( + ServiceGroup TestServiceGroup + ( + path : '/testServices'; + + Service TestService1 + ( + path : '/testService1'; + method : GET; + parameters : + ( + param : String ( location = query ), + param2 : Integer ( location = query ) + ); + response : test::gen::Trade <- test::gen::TestBinding; + security : []; + ) + Service TestService2 + ( + path : '/testService2'; + method : GET; + parameters : + ( + param1 : Boolean ( location = query ) + ); + response : test::gen::Trade <- test::gen::TestBinding; + security : []; + ) + ) +) + + +###Mapping +Mapping test::mapping +( + *test::gen::Trade: ServiceStore + { + ~service [test::testServiceStoreCompilationWithSingleService1] TestService + ( + ~paramMapping + ( + serializationFormat : 'CSV' + ) + ) + } +) + + +###Connection +ServiceStoreConnection simple::serviceStoreConnection +{ + store: test::testServiceStoreCompilationWithSingleService1; + baseUrl: 'http://baseUrl'; +} diff --git a/packages/legend-manual-tests/tsconfig.json b/packages/legend-manual-tests/tsconfig.json index c43689064e..317819c14a 100644 --- a/packages/legend-manual-tests/tsconfig.json +++ b/packages/legend-manual-tests/tsconfig.json @@ -23,6 +23,9 @@ }, { "path": "../legend-extension-dsl-serializer" + }, + { + "path": "../legend-extension-external-store-service" } ] } diff --git a/packages/legend-query-app/package.json b/packages/legend-query-app/package.json index 4bdf3109b1..2501ba4a28 100644 --- a/packages/legend-query-app/package.json +++ b/packages/legend-query-app/package.json @@ -45,6 +45,7 @@ "@finos/legend-extension-dsl-serializer": "workspace:*", "@finos/legend-extension-dsl-text": "workspace:*", "@finos/legend-extension-external-format-json-schema": "workspace:*", + "@finos/legend-extension-external-store-service": "workspace:*", "@finos/legend-query": "workspace:*", "@finos/legend-shared": "workspace:*", "@types/react": "17.0.32", diff --git a/packages/legend-query-app/src/index.tsx b/packages/legend-query-app/src/index.tsx index ee398772d4..4aa53500b0 100644 --- a/packages/legend-query-app/src/index.tsx +++ b/packages/legend-query-app/src/index.tsx @@ -20,6 +20,7 @@ import { EFJSONSchema_GraphPreset } from '@finos/legend-extension-external-forma import { BrowserConsole } from '@finos/legend-shared'; import { DSLDiagram_GraphPreset } from '@finos/legend-extension-dsl-diagram'; import { DSLSerializer_GraphPreset } from '@finos/legend-extension-dsl-serializer'; +import { ESService_GraphPreset } from '@finos/legend-extension-external-store-service'; import { DSLDataSpace_QueryPreset } from '@finos/legend-extension-dsl-data-space'; export class LegendQueryApplication { @@ -32,6 +33,7 @@ export class LegendQueryApplication { new DSLDataSpace_QueryPreset(), new EFJSONSchema_GraphPreset(), new DSLSerializer_GraphPreset(), + new ESService_GraphPreset(), ]) .withLoggers([new BrowserConsole()]) .start() diff --git a/packages/legend-query-app/tsconfig.json b/packages/legend-query-app/tsconfig.json index f017489578..976340307b 100644 --- a/packages/legend-query-app/tsconfig.json +++ b/packages/legend-query-app/tsconfig.json @@ -14,6 +14,7 @@ { "path": "../legend-query" }, { "path": "../legend-extension-dsl-diagram" }, { "path": "../legend-extension-dsl-serializer" }, + { "path": "../legend-extension-external-store-service" }, { "path": "../legend-extension-dsl-text" }, { "path": "../legend-extension-dsl-data-space" }, { "path": "../legend-extension-external-format-json-schema" } diff --git a/packages/legend-studio-app/package.json b/packages/legend-studio-app/package.json index 2a62d42c8e..3d850d55bc 100644 --- a/packages/legend-studio-app/package.json +++ b/packages/legend-studio-app/package.json @@ -45,6 +45,7 @@ "@finos/legend-extension-dsl-serializer": "workspace:*", "@finos/legend-extension-dsl-text": "workspace:*", "@finos/legend-extension-external-format-json-schema": "workspace:*", + "@finos/legend-extension-external-store-service": "workspace:*", "@finos/legend-shared": "workspace:*", "@finos/legend-studio": "workspace:*", "@finos/legend-studio-extension-query-builder": "workspace:*", diff --git a/packages/legend-studio-app/src/index.tsx b/packages/legend-studio-app/src/index.tsx index 2c868ff0fd..1dc190c159 100644 --- a/packages/legend-studio-app/src/index.tsx +++ b/packages/legend-studio-app/src/index.tsx @@ -22,6 +22,7 @@ import { BrowserConsole } from '@finos/legend-shared'; import { DSLDiagram_StudioPreset } from '@finos/legend-extension-dsl-diagram'; import { DSLSerializer_StudioPreset } from '@finos/legend-extension-dsl-serializer'; import { DSLDataSpace_StudioPreset } from '@finos/legend-extension-dsl-data-space'; +import { ESService_StudioPreset } from '@finos/legend-extension-external-store-service'; export class LegendStudioApplication { static run(baseUrl: string): void { @@ -34,6 +35,7 @@ export class LegendStudioApplication { new EFJSONSchema_GraphPreset(), new QueryBuilder_StudioPreset(), new DSLSerializer_StudioPreset(), + new ESService_StudioPreset(), ]) .withLoggers([new BrowserConsole()]) .start() diff --git a/packages/legend-studio-app/tsconfig.json b/packages/legend-studio-app/tsconfig.json index 1f11d4b102..b91e567802 100644 --- a/packages/legend-studio-app/tsconfig.json +++ b/packages/legend-studio-app/tsconfig.json @@ -14,6 +14,7 @@ { "path": "../legend-shared" }, { "path": "../legend-extension-dsl-diagram" }, { "path": "../legend-extension-dsl-serializer" }, + { "path": "../legend-extension-external-store-service" }, { "path": "../legend-extension-dsl-text" }, { "path": "../legend-extension-dsl-data-space" }, { "path": "../legend-extension-external-format-json-schema" }, diff --git a/packages/legend-studio/src/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.tsx b/packages/legend-studio/src/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.tsx index c9b54a9909..83299b38cf 100644 --- a/packages/legend-studio/src/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.tsx +++ b/packages/legend-studio/src/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.tsx @@ -93,7 +93,10 @@ export const InstanceSetImplementationSourceExplorer = observer( mappingEditorState.currentTabState instanceof MappingElementState ? mappingEditorState.currentTabState : undefined; - const srcElement = getMappingElementSource(setImplementation); + const srcElement = getMappingElementSource( + setImplementation, + editorStore.pluginManager.getStudioPlugins(), + ); const sourceLabel = getSourceElementLabel(srcElement); // `null` is when we want to open the modal using the existing source // `undefined` is to close the source modal diff --git a/packages/legend-studio/src/index.ts b/packages/legend-studio/src/index.ts index c33e3f61e0..a766007e8c 100644 --- a/packages/legend-studio/src/index.ts +++ b/packages/legend-studio/src/index.ts @@ -70,3 +70,6 @@ export * from './stores/StoreRelational_StudioPlugin_Extension'; export { ServicePureExecutionState } from './stores/editor-state/element-editor-state/service/ServiceExecutionState'; export { MappingExecutionState } from './stores/editor-state/element-editor-state/mapping/MappingExecutionState'; export { MappingTestState } from './stores/editor-state/element-editor-state/mapping/MappingTestState'; +export * from './stores/editor-state/element-editor-state/mapping/MappingEditorState'; +export { MappingElementState } from './stores/editor-state/element-editor-state/mapping/MappingElementState'; +export { UnsupportedInstanceSetImplementationState } from './stores/editor-state/element-editor-state/mapping/UnsupportedInstanceSetImplementationState'; diff --git a/packages/legend-studio/src/stores/DSLMapping_StudioPlugin_Extension.ts b/packages/legend-studio/src/stores/DSLMapping_StudioPlugin_Extension.ts index abb5dc50ad..98b7fdc420 100644 --- a/packages/legend-studio/src/stores/DSLMapping_StudioPlugin_Extension.ts +++ b/packages/legend-studio/src/stores/DSLMapping_StudioPlugin_Extension.ts @@ -17,11 +17,34 @@ import type { DSL_StudioPlugin_Extension } from './StudioPlugin'; import type { ConnectionValueState } from './editor-state/element-editor-state/connection/ConnectionEditorState'; import type { EditorStore } from './EditorStore'; -import type { Store, Connection, Runtime } from '@finos/legend-graph'; +import type { + Store, + Connection, + Runtime, + SetImplementation, +} from '@finos/legend-graph'; import type { ServicePureExecutionState } from './editor-state/element-editor-state/service/ServiceExecutionState'; import type { MappingTestState } from './editor-state/element-editor-state/mapping/MappingTestState'; import type { MappingExecutionState } from './editor-state/element-editor-state/mapping/MappingExecutionState'; import type { NewConnectionValueDriver } from './NewElementState'; +import type { + MappingElement, + MappingElementSource, +} from './editor-state/element-editor-state/mapping/MappingEditorState'; +import type { MappingElementState } from './editor-state/element-editor-state/mapping/MappingElementState'; + +export type MappingElementSourceGetter = ( + mappingElement: MappingElement, +) => MappingElementSource | undefined; + +export type SetImplemtationClassifier = ( + setImplementation: SetImplementation, +) => string | undefined; + +export type MappingElementStateCreator = ( + mappingElement: MappingElement | undefined, + editorStore: EditorStore, +) => MappingElementState | undefined; export type DefaultConnectionValueBuilder = ( store: Store, @@ -83,6 +106,21 @@ export type TEMP__ServiceTestRuntimeConnectionBuilder = ( export interface DSLMapping_StudioPlugin_Extension extends DSL_StudioPlugin_Extension { + /** + * Get the list of extra set implementation classifiers. + */ + getExtraSetImplementationClassifiers?(): SetImplemtationClassifier[]; + + /** + * Get the list of the mapping element state creators for the given class mapping. + */ + getExtraMappingElementStateCreators?(): MappingElementStateCreator[]; + + /** + * Get the list of the element source getters for the given class mapping. + */ + getExtraMappingElementSourceGetters?(): MappingElementSourceGetter[]; + /** * Get the list of the default connection value builder for a specified store. */ diff --git a/packages/legend-studio/src/stores/EditorGraphState.ts b/packages/legend-studio/src/stores/EditorGraphState.ts index 584c041961..9598d68a5a 100644 --- a/packages/legend-studio/src/stores/EditorGraphState.ts +++ b/packages/legend-studio/src/stores/EditorGraphState.ts @@ -78,7 +78,6 @@ import { Measure, Unit, Database, - ServiceStore, SectionIndex, RootRelationalInstanceSetImplementation, EmbeddedRelationalInstanceSetImplementation, @@ -93,6 +92,7 @@ import { ActionAlertType, } from '@finos/legend-application'; import { CONFIGURATION_EDITOR_TAB } from './editor-state/ProjectConfigurationEditorState'; +import type { DSLMapping_StudioPlugin_Extension } from './DSLMapping_StudioPlugin_Extension'; export enum GraphBuilderStatus { SUCCEEDED = 'SUCCEEDED', @@ -1134,8 +1134,6 @@ export class EditorGraphState { return PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE; } else if (element instanceof Database) { return PACKAGEABLE_ELEMENT_TYPE.DATABASE; - } else if (element instanceof ServiceStore) { - return PACKAGEABLE_ELEMENT_TYPE.SERVICE_STORE; } else if (element instanceof Mapping) { return PACKAGEABLE_ELEMENT_TYPE.MAPPING; } else if (element instanceof Service) { @@ -1171,9 +1169,7 @@ export class EditorGraphState { } /* @MARKER: NEW CLASS MAPPING TYPE SUPPORT --- consider adding class mapping type handler here whenever support for a new one is added to the app */ - getSetImplementationType( - setImplementation: SetImplementation, - ): SET_IMPLEMENTATION_TYPE { + getSetImplementationType(setImplementation: SetImplementation): string { if (setImplementation instanceof PureInstanceSetImplementation) { return SET_IMPLEMENTATION_TYPE.PUREINSTANCE; } else if (setImplementation instanceof OperationSetImplementation) { @@ -1193,8 +1189,22 @@ export class EditorGraphState { } else if (setImplementation instanceof AggregationAwareSetImplementation) { return SET_IMPLEMENTATION_TYPE.AGGREGATION_AWARE; } + const extraSetImplementationClassifiers = this.editorStore.pluginManager + .getStudioPlugins() + .flatMap( + (plugin) => + ( + plugin as DSLMapping_StudioPlugin_Extension + ).getExtraSetImplementationClassifiers?.() ?? [], + ); + for (const Classifier of extraSetImplementationClassifiers) { + const setImplementationClassifier = Classifier(setImplementation); + if (setImplementationClassifier) { + return setImplementationClassifier; + } + } throw new UnsupportedOperationError( - `Can't classify set implementation`, + `Can't classify set implementation: no compatible classifer available from plugins`, setImplementation, ); } diff --git a/packages/legend-studio/src/stores/EditorStore.ts b/packages/legend-studio/src/stores/EditorStore.ts index d0b37a4e4d..50da1585b8 100644 --- a/packages/legend-studio/src/stores/EditorStore.ts +++ b/packages/legend-studio/src/stores/EditorStore.ts @@ -102,7 +102,6 @@ import { ConcreteFunctionDefinition, Measure, Database, - ServiceStore, FlatData, Mapping, Service, @@ -1034,7 +1033,6 @@ export class EditorStore { } else if ( element instanceof Measure || element instanceof Database || - element instanceof ServiceStore || element instanceof FlatData ) { return new UnsupportedElementEditorState(this, element); diff --git a/packages/legend-studio/src/stores/NewElementState.tsx b/packages/legend-studio/src/stores/NewElementState.tsx index 975cebdafb..7801194aaf 100644 --- a/packages/legend-studio/src/stores/NewElementState.tsx +++ b/packages/legend-studio/src/stores/NewElementState.tsx @@ -66,7 +66,6 @@ import { FlatDataConnection, Database, PackageableElementExplicitReference, - ServiceStore, RelationalDatabaseConnection, DatabaseType, StaticDatasourceSpecification, @@ -647,9 +646,6 @@ export class NewElementState { case PACKAGEABLE_ELEMENT_TYPE.DATABASE: element = new Database(name); break; - case PACKAGEABLE_ELEMENT_TYPE.SERVICE_STORE: - element = new ServiceStore(name); - break; case PACKAGEABLE_ELEMENT_TYPE.SERVICE: { const service = new Service(name); const mapping = Mapping.createStub(); // since it does not really make sense to start with the first available mapping, we start with a stub diff --git a/packages/legend-studio/src/stores/editor-state/GrammarTextEditorState.ts b/packages/legend-studio/src/stores/editor-state/GrammarTextEditorState.ts index 72a2f72d8b..29e18362f3 100644 --- a/packages/legend-studio/src/stores/editor-state/GrammarTextEditorState.ts +++ b/packages/legend-studio/src/stores/editor-state/GrammarTextEditorState.ts @@ -41,7 +41,6 @@ import { Measure, Database, RelationalDatabaseConnection, - ServiceStore, } from '@finos/legend-graph'; import { GRAMMAR_ELEMENT_TYPE_LABEL } from '@finos/legend-application'; @@ -112,8 +111,6 @@ export class GrammarTextEditorState { typeLabel = GRAMMAR_ELEMENT_TYPE_LABEL.FLAT_DATA; } else if (element instanceof Database) { typeLabel = GRAMMAR_ELEMENT_TYPE_LABEL.DATABASE; - } else if (element instanceof ServiceStore) { - typeLabel = GRAMMAR_ELEMENT_TYPE_LABEL.SERVICE_STORE; } else if (element instanceof Mapping) { typeLabel = GRAMMAR_ELEMENT_TYPE_LABEL.MAPPING; } else if (element instanceof Service) { diff --git a/packages/legend-studio/src/stores/editor-state/element-editor-state/RuntimeEditorState.ts b/packages/legend-studio/src/stores/editor-state/element-editor-state/RuntimeEditorState.ts index 1c6f3d3333..6adf6c3726 100644 --- a/packages/legend-studio/src/stores/editor-state/element-editor-state/RuntimeEditorState.ts +++ b/packages/legend-studio/src/stores/editor-state/element-editor-state/RuntimeEditorState.ts @@ -556,7 +556,10 @@ export class IdentifiedConnectionsPerClassEditorTabState extends IdentifiedConne this.runtimeEditorState.runtimeValue.mappings.flatMap((mapping) => getAllClassMappings(mapping.value) .map((setImplementation) => - getMappingElementSource(setImplementation), + getMappingElementSource( + setImplementation, + this.editorStore.pluginManager.getStudioPlugins(), + ), ) .filter((source): source is Class => source instanceof Class), ), diff --git a/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingEditorState.ts b/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingEditorState.ts index 1092b32a06..4217098143 100644 --- a/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingEditorState.ts +++ b/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingEditorState.ts @@ -109,6 +109,8 @@ import { updateRootSetImplementationOnDelete, } from '@finos/legend-graph'; import { LambdaEditorState } from '@finos/legend-application'; +import type { DSLMapping_StudioPlugin_Extension } from '../../../DSLMapping_StudioPlugin_Extension'; +import type { StudioPlugin } from '../../../StudioPlugin'; export interface MappingExplorerTreeNodeData extends TreeNodeData { mappingElement: MappingElement; @@ -180,6 +182,7 @@ export const getMappingElementTarget = ( /* @MARKER: NEW CLASS MAPPING TYPE SUPPORT --- consider adding class mapping type handler here whenever support for a new one is added to the app */ export const getMappingElementSource = ( mappingElement: MappingElement, + plugins?: StudioPlugin[], ): MappingElementSource | undefined => { if (mappingElement instanceof OperationSetImplementation) { // NOTE: we don't need to resolve operation union because at the end of the day, it uses other class mappings @@ -199,6 +202,7 @@ export const getMappingElementSource = ( mappingElement.rootInstanceSetImplementation, FlatDataInstanceSetImplementation, ), + plugins, ); } else if ( mappingElement instanceof RootRelationalInstanceSetImplementation @@ -210,10 +214,28 @@ export const getMappingElementSource = ( return mappingElement.rootInstanceSetImplementation.mainTableAlias?.relation .value; } else if (mappingElement instanceof AggregationAwareSetImplementation) { - return getMappingElementSource(mappingElement.mainSetImplementation); + return getMappingElementSource( + mappingElement.mainSetImplementation, + plugins, + ); + } + if (plugins !== undefined) { + const extraMappingElementSourceGetters = plugins.flatMap( + (plugin) => + ( + plugin as DSLMapping_StudioPlugin_Extension + ).getExtraMappingElementSourceGetters?.() ?? [], + ); + for (const sourceGetter of extraMappingElementSourceGetters) { + const mappingElementSource = sourceGetter(mappingElement); + if (mappingElementSource) { + return mappingElementSource; + } + } } + throw new UnsupportedOperationError( - `Can't derive source of mapping element`, + `Can't derive source of mapping element: no compatible source available from plugins`, mappingElement, ); }; @@ -796,7 +818,10 @@ export class MappingEditorState extends ElementEditorState { setImplementation: InstanceSetImplementation, newSource: MappingElementSource | undefined, ): GeneratorFn { - const currentSource = getMappingElementSource(setImplementation); + const currentSource = getMappingElementSource( + setImplementation, + this.editorStore.pluginManager.getStudioPlugins(), + ); if (currentSource !== newSource) { if ( setImplementation instanceof PureInstanceSetImplementation && @@ -1017,6 +1042,23 @@ export class MappingEditorState extends ElementEditorState { mappingElement, ); } + const extraMappingElementStateCreators = this.editorStore.pluginManager + .getStudioPlugins() + .flatMap( + (plugin) => + ( + plugin as DSLMapping_StudioPlugin_Extension + ).getExtraMappingElementStateCreators?.() ?? [], + ); + for (const elementStateCreator of extraMappingElementStateCreators) { + const mappingElementState = elementStateCreator( + mappingElement, + this.editorStore, + ); + if (mappingElementState) { + return mappingElementState; + } + } return new MappingElementState(this.editorStore, mappingElement); } @@ -1322,7 +1364,10 @@ export class MappingEditorState extends ElementEditorState { this.editorStore.graphManagerState.graphManager.HACKY_createGetAllLambda( setImplementation.class.value, ); - const source = getMappingElementSource(setImplementation); + const source = getMappingElementSource( + setImplementation, + this.editorStore.pluginManager.getStudioPlugins(), + ); if (setImplementation instanceof OperationSetImplementation) { this.editorStore.applicationStore.notifyWarning( `Can't auto-generate input data for operation class mapping. Please pick a concrete class mapping instead`, diff --git a/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingElementDecorator.ts b/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingElementDecorator.ts index 9bdf99d3b5..d18b041dd1 100644 --- a/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingElementDecorator.ts +++ b/packages/legend-studio/src/stores/editor-state/element-editor-state/mapping/MappingElementDecorator.ts @@ -33,6 +33,7 @@ import type { RootRelationalInstanceSetImplementation, AggregationAwareSetImplementation, PropertyMapping, + InstanceSetImplementation, } from '@finos/legend-graph'; import { getAllClassMappings, @@ -477,7 +478,12 @@ export class MappingElementDecorator implements SetImplementationVisitor { visit_AggregationAwareSetImplementation( setImplementation: AggregationAwareSetImplementation, ): void { - throw new UnsupportedOperationError(); + return; + } + + visit_SetImplementation(setImplementation: InstanceSetImplementation): void { + //TODO: Implement this later https://github.com/finos/legend-studio/pull/580 + return; } } @@ -566,6 +572,11 @@ export class MappingElementDecorationCleaner visit_AggregationAwareSetImplementation( setImplementation: AggregationAwareSetImplementation, ): void { - throw new UnsupportedOperationError(); + return; + } + + visit_SetImplementation(setImplementation: InstanceSetImplementation): void { + //TODO: Implement this later https://github.com/finos/legend-studio/pull/580 + return; } } diff --git a/packages/legend-studio/src/stores/shared/PackageTreeUtil.ts b/packages/legend-studio/src/stores/shared/PackageTreeUtil.ts index 1ed4069cc7..05caac71a8 100644 --- a/packages/legend-studio/src/stores/shared/PackageTreeUtil.ts +++ b/packages/legend-studio/src/stores/shared/PackageTreeUtil.ts @@ -32,7 +32,6 @@ import { Measure, Unit, Database, - ServiceStore, FlatData, Mapping, Service, @@ -64,8 +63,6 @@ const getElementProjectExplorerDnDType = ( return CORE_DND_TYPE.PROJECT_EXPLORER_FLAT_DATA; } else if (element instanceof Database) { return CORE_DND_TYPE.PROJECT_EXPLORER_DATABASE; - } else if (element instanceof ServiceStore) { - return CORE_DND_TYPE.PROJECT_EXPLORER_SERVICE_STORE; } else if (element instanceof Mapping) { return CORE_DND_TYPE.PROJECT_EXPLORER_MAPPING; } else if (element instanceof PackageableRuntime) { diff --git a/tsconfig.json b/tsconfig.json index f082723873..5ce95f7a66 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,6 +39,9 @@ }, { "path": "packages/legend-extension-external-format-json-schema" + }, + { + "path": "packages/legend-extension-external-store-service" } ] } diff --git a/yarn.lock b/yarn.lock index 5fe4ad098a..d06ab5c855 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2087,6 +2087,35 @@ __metadata: languageName: unknown linkType: soft +"@finos/legend-extension-external-store-service@workspace:*, @finos/legend-extension-external-store-service@workspace:packages/legend-extension-external-store-service": + version: 0.0.0-use.local + resolution: "@finos/legend-extension-external-store-service@workspace:packages/legend-extension-external-store-service" + dependencies: + "@finos/legend-art": "workspace:*" + "@finos/legend-dev-utils": "workspace:*" + "@finos/legend-extension-dsl-serializer": "workspace:*" + "@finos/legend-graph": "workspace:*" + "@finos/legend-model-storage": "workspace:*" + "@finos/legend-shared": "workspace:*" + "@finos/legend-studio": "workspace:*" + "@types/react": 17.0.32 + cross-env: 7.0.3 + eslint: 8.1.0 + jest: 27.3.1 + mobx: 6.3.5 + mobx-react-lite: 3.2.1 + monaco-editor: 0.29.1 + npm-run-all: 4.1.5 + react: 17.0.2 + rimraf: 3.0.2 + sass: 1.43.3 + serializr: 2.0.5 + typescript: 4.4.4 + peerDependencies: + react: ^17.0.0 + languageName: unknown + linkType: soft + "@finos/legend-graph@workspace:*, @finos/legend-graph@workspace:packages/legend-graph": version: 0.0.0-use.local resolution: "@finos/legend-graph@workspace:packages/legend-graph" @@ -2117,6 +2146,7 @@ __metadata: "@finos/legend-extension-dsl-diagram": "workspace:*" "@finos/legend-extension-dsl-serializer": "workspace:*" "@finos/legend-extension-dsl-text": "workspace:*" + "@finos/legend-extension-external-store-service": "workspace:*" "@finos/legend-graph": "workspace:*" "@finos/legend-shared": "workspace:*" axios: 0.24.0 @@ -2156,6 +2186,7 @@ __metadata: "@finos/legend-extension-dsl-serializer": "workspace:*" "@finos/legend-extension-dsl-text": "workspace:*" "@finos/legend-extension-external-format-json-schema": "workspace:*" + "@finos/legend-extension-external-store-service": "workspace:*" "@finos/legend-query": "workspace:*" "@finos/legend-shared": "workspace:*" "@types/react": 17.0.32 @@ -2319,6 +2350,7 @@ __metadata: "@finos/legend-extension-dsl-serializer": "workspace:*" "@finos/legend-extension-dsl-text": "workspace:*" "@finos/legend-extension-external-format-json-schema": "workspace:*" + "@finos/legend-extension-external-store-service": "workspace:*" "@finos/legend-shared": "workspace:*" "@finos/legend-studio": "workspace:*" "@finos/legend-studio-extension-query-builder": "workspace:*"