Skip to content

Commit

Permalink
display all dataspace executables in Legend Query (#3463)
Browse files Browse the repository at this point in the history
  • Loading branch information
YannanGao-gs authored Aug 28, 2024
1 parent 6f26fea commit 2770a48
Show file tree
Hide file tree
Showing 8 changed files with 1,198 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilly-apes-dress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@finos/legend-extension-dsl-data-space': patch
---

Display all dataspace executables in Legend Query
3 changes: 3 additions & 0 deletions .changeset/tasty-crews-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
'@finos/legend-application-query': patch
---
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
*/

import {
QueryProjectCoordinates,
extractElementNameFromPath,
type Query,
type RawLambda,
type QuerySearchSpecification,
type RawLambda,
QueryProjectCoordinates,
extractElementNameFromPath,
} from '@finos/legend-graph';
import {
type DepotServerClient,
StoreProjectData,
} from '@finos/legend-server-depot';
import { filterByType, guaranteeNonNullable, uuid } from '@finos/legend-shared';
import { IllegalStateError, uuid } from '@finos/legend-shared';
import {
type QueryBuilderState,
QueryBuilderDataBrowserWorkflow,
} from '@finos/legend-query-builder';
import {
parseGACoordinates,
type ProjectGAVCoordinates,
parseGACoordinates,
} from '@finos/legend-storage';
import {
QueryBuilderActionConfig_QueryApplication,
Expand All @@ -42,15 +42,17 @@ import {
import type { LegendQueryApplicationStore } from '../LegendQueryBaseStore.js';
import {
DSL_DataSpace_getGraphManagerExtension,
DataSpaceExecutableTemplate,
getDataSpace,
retrieveAnalyticsResultCache,
getExecutionContextFromDataspaceExecutable,
getQueryFromDataspaceExecutable,
DataSpacePackageableElementExecutable,
} from '@finos/legend-extension-dsl-data-space/graph';
import {
type DataSpaceInfo,
DataSpaceQueryBuilderState,
createQueryClassTaggedValue,
createQueryDataSpaceTaggedValue,
type DataSpaceInfo,
} from '@finos/legend-extension-dsl-data-space/application';
import { createDataSpaceDepoRepo } from './DataSpaceQueryBuilderHelper.js';

Expand Down Expand Up @@ -93,21 +95,40 @@ export class DataSpaceTemplateQueryCreatorStore extends QueryEditorStore {
this.dataSpacePath,
this.graphManagerState.graph,
);
const dataSpaceExecutableTemplate = guaranteeNonNullable(
dataSpace.executables
?.filter(filterByType(DataSpaceExecutableTemplate))
.find((executable) => executable.id === this.templateQueryId),
`Can't find template query with id '${this.templateQueryId}'`,
let template = dataSpace.executables?.find(
(executable) => executable.id === this.templateQueryId,
);
const executionContext = guaranteeNonNullable(
dataSpaceExecutableTemplate.executionContextKey
? dataSpace.executionContexts.filter(
(ec) => ec.name === dataSpaceExecutableTemplate.executionContextKey,
)[0]
: dataSpace.defaultExecutionContext,
`Can't find execution context '${dataSpaceExecutableTemplate.executionContextKey}'`,
if (!template) {
template = dataSpace.executables?.find(
(executable) =>
executable instanceof DataSpacePackageableElementExecutable &&
executable.executable.value.path === this.templateQueryId,
);
}
if (!template) {
throw new IllegalStateError(
`Can't find template query with id '${this.templateQueryId}'`,
);
}
const executionContext = getExecutionContextFromDataspaceExecutable(
dataSpace,
template,
);
if (!executionContext) {
throw new IllegalStateError(
`Can't find a correpsonding execution context`,
);
}
const query = getQueryFromDataspaceExecutable(
template,
this.graphManagerState,
);
this.templateQueryTitle = dataSpaceExecutableTemplate.title;
if (!query) {
throw new IllegalStateError(
`Can't fetch query from dataspace executable`,
);
}
this.templateQueryTitle = template.title;
let dataSpaceAnalysisResult;
try {
const project = StoreProjectData.serialization.fromJson(
Expand Down Expand Up @@ -160,7 +181,7 @@ export class DataSpaceTemplateQueryCreatorStore extends QueryEditorStore {
);
queryBuilderState.setExecutionContext(executionContext);
queryBuilderState.propagateExecutionContextChange(executionContext);
queryBuilderState.initializeWithQuery(dataSpaceExecutableTemplate.query);
queryBuilderState.initializeWithQuery(query);
return queryBuilderState;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,62 @@ import {
useApplicationStore,
} from '@finos/legend-application';
import { DocumentationLink } from '@finos/legend-lego/application';
import { DataSpaceExecutableTemplate } from '../../graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js';
import type { DataSpaceExecutable } from '../../graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js';
import type { DataSpaceQueryBuilderState } from '../../stores/query-builder/DataSpaceQueryBuilderState.js';
import { DSL_DATA_SPACE_LEGEND_QUERY_DOCUMENTATION_KEY } from '../../__lib__/query/DSL_DataSpace_LegendQueryDocumentation.js';
import {
getExecutionContextFromDataspaceExecutable,
getQueryFromDataspaceExecutable,
} from '../../graph-manager/DSL_DataSpace_GraphManagerHelper.js';

const DataSpaceTemplateQueryDialog = observer(
(props: {
triggerElement: HTMLElement | null;
queryBuilderState: DataSpaceQueryBuilderState;
templateQueries: DataSpaceExecutableTemplate[];
templateQueries: DataSpaceExecutable[];
}) => {
const { triggerElement, queryBuilderState, templateQueries } = props;
const applicationStore = useApplicationStore();
const handleClose = (): void => {
queryBuilderState.setTemplateQueryDialogOpen(false);
};

const loadTemplateQuery = (template: DataSpaceExecutableTemplate): void => {
const executionContext =
queryBuilderState.dataSpace.executionContexts.find(
(c) => c.name === template.executionContextKey,
const loadTemplateQuery = (template: DataSpaceExecutable): void => {
const executionContext = getExecutionContextFromDataspaceExecutable(
queryBuilderState.dataSpace,
template,
);
if (!executionContext) {
applicationStore.notificationService.notifyError(
'Unable find an executionContext of this template query within current dataspace',
);
}
const query = getQueryFromDataspaceExecutable(
template,
queryBuilderState.graphManagerState,
);
if (!query) {
applicationStore.notificationService.notifyError(
'Unable get a query from this template query',
);
}
if (
query &&
executionContext &&
executionContext.hashCode !==
queryBuilderState.executionContext.hashCode
) {
queryBuilderState.setExecutionContext(executionContext);
queryBuilderState.propagateExecutionContextChange(executionContext);
queryBuilderState.initializeWithQuery(template.query);
queryBuilderState.initializeWithQuery(query);
queryBuilderState.onExecutionContextChange?.(executionContext);
} else {
queryBuilderState.initializeWithQuery(template.query);
} else if (query) {
queryBuilderState.initializeWithQuery(query);
}
handleClose();
};

const loadQuery = (template: DataSpaceExecutableTemplate): void => {
const loadQuery = (template: DataSpaceExecutable): void => {
if (queryBuilderState.changeDetectionState.hasChanged) {
applicationStore.alertService.setActionAlertInfo({
message:
Expand All @@ -89,9 +108,7 @@ const DataSpaceTemplateQueryDialog = observer(
}
};

const visitTemplateQuery = (
template: DataSpaceExecutableTemplate,
): void => {
const visitTemplateQuery = (template: DataSpaceExecutable): void => {
if (queryBuilderState.dataSpaceRepo.canVisitTemplateQuery) {
queryBuilderState.dataSpaceRepo.visitTemplateQuery(
queryBuilderState.dataSpace,
Expand Down Expand Up @@ -180,9 +197,7 @@ const DataSpaceQueryBuilderTemplateQueryPanel = observer(
(props: { queryBuilderState: DataSpaceQueryBuilderState }) => {
const { queryBuilderState } = props;
const templateQueryButtonRef = useRef<HTMLButtonElement>(null);
const templateQueries = queryBuilderState.dataSpace.executables?.filter(
(e) => e instanceof DataSpaceExecutableTemplate,
);
const templateQueries = queryBuilderState.dataSpace.executables;

const showTemplateQueries = (): void => {
queryBuilderState.setTemplateQueryDialogOpen(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,26 @@
* limitations under the License.
*/

import type { BasicModel, PureModel } from '@finos/legend-graph';
import {
type BasicModel,
type PureModel,
type GraphManagerState,
ConcreteFunctionDefinition,
PureExecution,
PureMultiExecution,
PureSingleExecution,
RawLambda,
RuntimePointer,
Service,
} from '@finos/legend-graph';
import { guaranteeNonNullable } from '@finos/legend-shared';
import { DataSpace } from '../graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js';
import {
type DataSpaceExecutable,
type DataSpaceExecutionContext,
DataSpace,
DataSpaceExecutableTemplate,
DataSpacePackageableElementExecutable,
} from '../graph/metamodel/pure/model/packageableElements/dataSpace/DSL_DataSpace_DataSpace.js';

export const getDataSpace = (path: string, graph: PureModel): DataSpace =>
graph.getExtensionElement(path, DataSpace, `Can't find data space '${path}'`);
Expand All @@ -26,3 +43,81 @@ export const getOwnDataSpace = (path: string, graph: BasicModel): DataSpace =>
graph.getOwnNullableExtensionElement(path, DataSpace),
`Can't find data space '${path}'`,
);

export const getExecutionContextFromDataspaceExecutable = (
dataSpace: DataSpace,
executable: DataSpaceExecutable,
): DataSpaceExecutionContext | undefined => {
let executionContext;
if (
executable instanceof DataSpaceExecutableTemplate ||
(executable instanceof DataSpacePackageableElementExecutable &&
executable.executable.value instanceof ConcreteFunctionDefinition)
) {
executionContext = executable.executionContextKey
? dataSpace.executionContexts.find(
(c) => c.name === executable.executionContextKey,
)
: dataSpace.defaultExecutionContext;
} else if (
executable instanceof DataSpacePackageableElementExecutable &&
executable.executable.value instanceof Service
) {
if (executable.executionContextKey) {
executionContext = dataSpace.executionContexts.find(
(c) => c.name === executable.executionContextKey,
);
} else if (executable.executable.value.execution instanceof PureExecution) {
const serviceExecution = executable.executable.value.execution;
const serviceMapping =
serviceExecution instanceof PureSingleExecution
? [serviceExecution.mapping?.value]
: serviceExecution instanceof PureMultiExecution
? serviceExecution.executionParameters?.map((p) => p.mapping.value)
: [];
const serviceRuntime =
serviceExecution instanceof PureSingleExecution
? serviceExecution.runtime instanceof RuntimePointer
? [serviceExecution.runtime.packageableRuntime.value]
: []
: serviceExecution instanceof PureMultiExecution
? serviceExecution.executionParameters
?.map((p) => p.runtime)
.filter((r) => r instanceof RuntimePointer)
.map((rp) => rp.packageableRuntime.value)
: [];
executionContext = dataSpace.executionContexts.find(
(c) =>
serviceMapping?.includes(c.mapping.value) &&
serviceRuntime?.includes(c.defaultRuntime.value),
);
}
}
return executionContext;
};

export const getQueryFromDataspaceExecutable = (
executable: DataSpaceExecutable,
graphManagerState: GraphManagerState,
): RawLambda | undefined => {
let query;
if (executable instanceof DataSpaceExecutableTemplate) {
query = executable.query;
} else if (executable instanceof DataSpacePackageableElementExecutable) {
if (executable.executable.value instanceof ConcreteFunctionDefinition) {
const functionDef = executable.executable.value;
query = new RawLambda(
functionDef.parameters.map((_param) =>
graphManagerState.graphManager.serializeRawValueSpecification(_param),
),
functionDef.expressionSequence,
);
} else if (
executable.executable.value instanceof Service &&
executable.executable.value.execution instanceof PureExecution
) {
query = executable.executable.value.execution.func;
}
}
return query;
};
Loading

0 comments on commit 2770a48

Please sign in to comment.