@finos/legend-extension-dsl-data-quality
Version:
Legend extension for Data Quality
312 lines (294 loc) • 11 kB
text/typescript
/**
* 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 { action, flow, makeObservable, observable } from 'mobx';
import {
type Class,
type Mapping,
type PackageableElement,
type Runtime,
getMappingCompatibleClasses,
PackageableElementExplicitReference,
RuntimePointer,
} from '@finos/legend-graph';
import type {
EditorStore,
ElementEditorState,
} from '@finos/legend-application-studio';
import {
DataQualityClassValidationsConfiguration,
DataSpaceDataQualityExecutionContext,
MappingAndRuntimeDataQualityExecutionContext,
} from '../../graph/metamodel/pure/packageableElements/data-quality/DataQualityValidationConfiguration.js';
import { DataQualityState } from './DataQualityState.js';
import {
ResolvedDataSpaceEntityWithOrigin,
type DataSpaceExecutionContext,
DataSpace,
resolveUsableDataSpaceClasses,
} from '@finos/legend-extension-dsl-data-space/graph';
import { CLASS_ELEMENT_CREATION_BASIS } from '../DSL_DataQuality_ElementDriver.js';
import {
type GeneratorFn,
assertType,
filterByType,
guaranteeNonNullable,
guaranteeType,
} from '@finos/legend-shared';
import {
dataQualityClassValidation_setContextDataQualityContext,
dataQualityClassValidation_setDataQualityContext,
dataQualityClassValidation_setDataQualityGraphFetchTree,
dataQualityClassValidation_setFilter,
dataQualityClassValidation_setRuntimeDataQualityContext,
} from '../../graph-manager/DSL_DataQuality_GraphModifierHelper.js';
import { DataQualityGraphFetchTreeState } from './DataQualityGraphFetchTreeState.js';
import { DataQualityResultState } from './DataQualityResultState.js';
export class DataQualityClassValidationState extends DataQualityState {
dataSpace?: DataSpace | undefined;
dataSpaces: ResolvedDataSpaceEntityWithOrigin[] = [];
validationElementCreationBasis: CLASS_ELEMENT_CREATION_BASIS =
CLASS_ELEMENT_CREATION_BASIS.MAPPING_RUNTIME_BASED;
constructor(
editorStore: EditorStore,
element: DataQualityClassValidationsConfiguration,
) {
super(editorStore, element);
makeObservable(this, {
dataSpaces: observable,
dataSpace: observable,
onDataSpaceChange: action,
initializeState: action,
updateElementOnMappingChange: action,
updateElementOnRuntimeChange: action,
updateElementOnExecutionContextChange: action,
updateElementOnDataSpaceChange: action,
loadDataSpaces: flow,
});
this.initializeState();
}
reprocess(
newElement: PackageableElement,
editorStore: EditorStore,
): ElementEditorState {
const element = guaranteeType(
newElement,
DataQualityClassValidationsConfiguration,
'Element inside data quality class validation editor state must be a class validation element',
);
return new DataQualityClassValidationState(editorStore, element);
}
override get constraintsConfigurationElement(): DataQualityClassValidationsConfiguration {
return guaranteeType(
this.element,
DataQualityClassValidationsConfiguration,
'Element inside data quality class validation state must be a data quality class validation configuration element',
);
}
initializeState() {
let classOptions: Class[] = [];
if (
this.constraintsConfigurationElement.context instanceof
MappingAndRuntimeDataQualityExecutionContext
) {
this.validationElementCreationBasis =
CLASS_ELEMENT_CREATION_BASIS.MAPPING_RUNTIME_BASED;
this.dataQualityQueryBuilderState.executionContextState.setMapping(
this.constraintsConfigurationElement.context.mapping.value,
);
this.dataQualityQueryBuilderState.executionContextState.setRuntimeValue(
new RuntimePointer(
this.constraintsConfigurationElement.context.runtime,
),
);
classOptions = getMappingCompatibleClasses(
guaranteeNonNullable(
this.dataQualityQueryBuilderState.executionContextState.mapping,
),
this.graphManagerState.usableClasses,
);
} else if (
this.constraintsConfigurationElement.context instanceof
DataSpaceDataQualityExecutionContext
) {
this.validationElementCreationBasis =
CLASS_ELEMENT_CREATION_BASIS.DATASPACE_BASED;
this.dataSpace =
this.constraintsConfigurationElement.context.dataSpace.value;
this.executionContext = this.dataSpace.defaultExecutionContext;
this.dataQualityQueryBuilderState.executionContextState.setMapping(
this.dataSpace.defaultExecutionContext.mapping.value,
);
this.dataQualityQueryBuilderState.executionContextState.setRuntimeValue(
new RuntimePointer(
this.dataSpace.defaultExecutionContext.defaultRuntime,
),
);
classOptions = resolveUsableDataSpaceClasses(
this.dataSpace,
guaranteeNonNullable(
this.dataQualityQueryBuilderState.executionContextState.mapping,
),
this.graphManagerState,
);
}
this.initializeGraphFetchTreeState(
this.constraintsConfigurationElement.dataQualityRootGraphFetchTree,
);
this.initializeFilterState(this.constraintsConfigurationElement.filter);
if (this.constraintsConfigurationElement.dataQualityRootGraphFetchTree) {
this.dataQualityQueryBuilderState.setSourceElement(
this.constraintsConfigurationElement.dataQualityRootGraphFetchTree.class
.value,
);
} else {
this.dataQualityQueryBuilderState.setSourceElement(classOptions[0]);
this.dataQualityGraphFetchTreeState = new DataQualityGraphFetchTreeState(
this,
);
dataQualityClassValidation_setDataQualityGraphFetchTree(
this.constraintsConfigurationElement,
this.dataQualityGraphFetchTreeState.treeData
? this.dataQualityGraphFetchTreeState.treeData.tree
: undefined,
);
}
}
changeMapping(val: Mapping, options?: { keepQueryContent?: boolean }): void {
//reset result
this.dataQualityQueryBuilderState.executionContextState.setMapping(val);
this.dataQualityQueryBuilderState.executionContextState.setRuntimeValue(
undefined,
);
this.dataQualityQueryBuilderState.explorerState.setTreeData(undefined);
this.dataQualityQueryBuilderState.setSourceElement(undefined);
this.dataQualityGraphFetchTreeState = new DataQualityGraphFetchTreeState(
this,
);
this.structuralValidationsGraphFetchTreeState =
new DataQualityGraphFetchTreeState(this);
this.resultState = new DataQualityResultState(this);
}
changeRuntime(val: Runtime) {
this.dataQualityQueryBuilderState.changeRuntime(val);
this.resultState = new DataQualityResultState(this);
}
updateElementOnMappingChange() {
const mappingAndRuntimeExecutionContext =
new MappingAndRuntimeDataQualityExecutionContext();
mappingAndRuntimeExecutionContext.mapping =
PackageableElementExplicitReference.create(
guaranteeNonNullable(
this.dataQualityQueryBuilderState.executionContextState.mapping,
),
);
guaranteeNonNullable(
this.dataQualityQueryBuilderState.executionContextState.runtimeValue,
);
mappingAndRuntimeExecutionContext.runtime = (
this.dataQualityQueryBuilderState.executionContextState
.runtimeValue as RuntimePointer
).packageableRuntime;
dataQualityClassValidation_setDataQualityContext(
this.constraintsConfigurationElement,
mappingAndRuntimeExecutionContext,
);
dataQualityClassValidation_setDataQualityGraphFetchTree(
this.constraintsConfigurationElement,
undefined,
);
dataQualityClassValidation_setFilter(
this.constraintsConfigurationElement,
undefined,
);
}
updateElementOnRuntimeChange(runtime: Runtime) {
assertType(runtime, RuntimePointer);
dataQualityClassValidation_setRuntimeDataQualityContext(
this.constraintsConfigurationElement,
runtime.packageableRuntime,
this.editorStore.changeDetectionState.observerContext,
);
}
updateElementOnExecutionContextChange(context: string) {
dataQualityClassValidation_setContextDataQualityContext(
this.constraintsConfigurationElement,
context,
);
}
propagateExecutionContextChange(
executionContext: DataSpaceExecutionContext,
): void {
const mapping = executionContext.mapping.value;
this.changeMapping(mapping);
this.dataQualityQueryBuilderState.changeRuntime(
new RuntimePointer(executionContext.defaultRuntime),
);
const compatibleClasses = resolveUsableDataSpaceClasses(
guaranteeNonNullable(this.dataSpace),
mapping,
this.graphManagerState,
);
// if there is no chosen class or the chosen one is not compatible
// with the mapping then pick a compatible class if possible
if (
!this.dataQualityQueryBuilderState.sourceClass ||
!compatibleClasses.includes(this.dataQualityQueryBuilderState.sourceClass)
) {
const possibleNewClass = compatibleClasses[0];
if (possibleNewClass) {
this.changeSourceElement(possibleNewClass);
}
}
}
onDataSpaceChange(dataSpaceInfo: ResolvedDataSpaceEntityWithOrigin) {
this.dataSpace = guaranteeType(
this.graphManagerState.graph.getElement(dataSpaceInfo.path),
DataSpace,
);
this.setExecutionContext(this.dataSpace.defaultExecutionContext);
this.propagateExecutionContextChange(
this.dataSpace.defaultExecutionContext,
);
}
updateElementOnDataSpaceChange() {
const dataSpaceExecutionContext =
new DataSpaceDataQualityExecutionContext();
dataSpaceExecutionContext.context = this.executionContext.name;
dataSpaceExecutionContext.dataSpace =
PackageableElementExplicitReference.create(
guaranteeNonNullable(this.dataSpace),
);
dataQualityClassValidation_setDataQualityContext(
this.constraintsConfigurationElement,
dataSpaceExecutionContext,
);
this.updateElementOnClassChange();
}
*loadDataSpaces(): GeneratorFn<void> {
this.dataSpaces = this.graphManagerState.graph.allOwnElements
.filter(filterByType(DataSpace))
.map(
(e) =>
new ResolvedDataSpaceEntityWithOrigin(
undefined,
e.title,
e.name,
e.path,
e.defaultExecutionContext.name,
),
);
}
}