diff --git a/api/src/common/interfaces/utilities.interface.ts b/api/src/common/interfaces/utilities.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..f226c240a132a6508bab4981c213a784f27b751a --- /dev/null +++ b/api/src/common/interfaces/utilities.interface.ts @@ -0,0 +1 @@ +export type Dictionary<T> = { [key: string]: T }; \ No newline at end of file diff --git a/api/src/engine/connectors/datashield/main.connector.ts b/api/src/engine/connectors/datashield/main.connector.ts index a3622654e507cc5747d93ecd287dd2fe81c28247..104a4fe0db6e76f2feda3e54310cae9846d6bc00 100644 --- a/api/src/engine/connectors/datashield/main.connector.ts +++ b/api/src/engine/connectors/datashield/main.connector.ts @@ -1,7 +1,12 @@ import { Observable } from 'rxjs'; import { IEngineService } from 'src/engine/engine.interfaces'; +import { Domain } from 'src/engine/models/domain.model'; export default class DataShieldService implements IEngineService { + getDomain(): Domain[] { + throw new Error('Method not implemented.'); + } + demo(): string { return 'datashield'; } diff --git a/api/src/engine/connectors/exareme/interfaces/hierarchy.interface.ts b/api/src/engine/connectors/exareme/interfaces/hierarchy.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..6d0f02bd3b8dd5ec1cf6da521e93a412204fa51a --- /dev/null +++ b/api/src/engine/connectors/exareme/interfaces/hierarchy.interface.ts @@ -0,0 +1,8 @@ +import { VariableEntity } from "./variable-entity.interface"; + +export interface Hierarchy { + code: string; + label: string; + groups: Hierarchy[]; + variables: VariableEntity[]; +} \ No newline at end of file diff --git a/api/src/engine/connectors/exareme/interfaces/pathology.interface.ts b/api/src/engine/connectors/exareme/interfaces/pathology.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..d9dbea5ff6d3ed6f8fbd18c108e8d982d0a40695 --- /dev/null +++ b/api/src/engine/connectors/exareme/interfaces/pathology.interface.ts @@ -0,0 +1,9 @@ +import { Hierarchy } from "./Hierarchy.interface"; +import { VariableEntity } from "./variable-entity.interface"; + +export interface Pathology { + code: string; + label: string; + datasets: VariableEntity[]; + metadataHierarchy: Hierarchy; +} \ No newline at end of file diff --git a/api/src/engine/connectors/exareme/interfaces/variable-entity.interface.ts b/api/src/engine/connectors/exareme/interfaces/variable-entity.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..ce1ce25b461f5dd9e495cf27f6791f114cd5ade4 --- /dev/null +++ b/api/src/engine/connectors/exareme/interfaces/variable-entity.interface.ts @@ -0,0 +1,9 @@ +import { Variable } from "./variable.interface"; + +export interface VariableEntity extends Variable { + type?: 'nominal' | 'ordinal' | 'real' | 'integer' | 'text' | 'date'; + description?: string; + enumerations?: Variable[]; + group?: Variable[]; + info?: string; +} \ No newline at end of file diff --git a/api/src/engine/connectors/exareme/interfaces/variable.interface.ts b/api/src/engine/connectors/exareme/interfaces/variable.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..85174c8d88ca7ddf2e8fc320a7eb812fd3fe9d1d --- /dev/null +++ b/api/src/engine/connectors/exareme/interfaces/variable.interface.ts @@ -0,0 +1,4 @@ +export interface Variable { + code: string; + label?: string; +} \ No newline at end of file diff --git a/api/src/engine/connectors/exareme/main.connector.ts b/api/src/engine/connectors/exareme/main.connector.ts index b85b494bec2fb8c1de2ac8bda441e9c71c3da241..ae590365d74c0bdd3b875ae1d991f859f43fae9d 100644 --- a/api/src/engine/connectors/exareme/main.connector.ts +++ b/api/src/engine/connectors/exareme/main.connector.ts @@ -1,13 +1,57 @@ import { HttpService } from '@nestjs/axios'; import { Request } from 'express'; -import { map, Observable } from 'rxjs'; +import { firstValueFrom, map, Observable } from 'rxjs'; +import { Dictionary } from 'src/common/interfaces/utilities.interface'; import { IEngineOptions, IEngineService } from 'src/engine/engine.interfaces'; +import { Domain } from 'src/engine/models/domain.model'; +import { Group } from 'src/engine/models/group.model'; +import { Hierarchy } from './interfaces/Hierarchy.interface'; +import { Pathology } from './interfaces/pathology.interface'; +import { VariableEntity } from './interfaces/variable-entity.interface'; export default class ExaremeService implements IEngineService { constructor( private readonly options: IEngineOptions, private readonly httpService: HttpService, - ) {} + ) { } + + private hierarchyToGroup = (data: Hierarchy): Group => { + return { + id: data.code, + label: data.label, + groups: data.groups ? data.groups.map((child: Hierarchy) => this.hierarchyToGroup(child)) : [], + variables: [] + } + } + + private flattenGroups = (data: Hierarchy): Group[] => { + let groups: Group[] = [this.hierarchyToGroup(data)]; + + if (data.groups) { + groups = groups.concat(data.groups.flatMap(this.flattenGroups)); + } + + return groups; + } + + + async getDomain(): Promise<Domain[]> { + const path = this.options.baseurl + 'pathologies'; + + const data = await firstValueFrom(this.httpService.get(path)); + + const domains = data.data.map((data: Pathology): Domain => { + return { + id: data.code, + label: data.label, + groups: data.metadataHierarchy.groups.flatMap(this.flattenGroups), + datasets: [], + variables: [], + } + }) + + return domains; + } demo(): string { return 'exareme'; @@ -82,4 +126,49 @@ export default class ExaremeService implements IEngineService { .get<string>(path) .pipe(map((response) => response.data)); } + + private pathologiesHierarchies = ( + json: Pathology[] + ): Dictionary<Hierarchy> => { + const pathologiesDatasets: Dictionary<Hierarchy> = {}; + json.forEach(pathology => { + pathologiesDatasets[pathology.code] = pathology.metadataHierarchy; + }); + + return pathologiesDatasets; + }; + + private pathologiesVariables = (json: Pathology[]): Dictionary<VariableEntity[]> => { + const pathologiesVariables: Dictionary<VariableEntity[]> = {}; + json.forEach(pathology => { + let variables: VariableEntity[] = []; + + const dummyAccumulator = (node: any): void => { + if (node.variables) { + variables = [...variables, ...node.variables]; + } + + if (node.groups) { + return node.groups.map(dummyAccumulator); + } + }; + + if (pathology) { + dummyAccumulator(pathology.metadataHierarchy); + } + + pathologiesVariables[pathology.code] = variables; + }); + + return pathologiesVariables; + }; + + private pathologiesDatasets = (json: Pathology[]): Dictionary<VariableEntity[]> => { + const pathologiesDatasets: Dictionary<VariableEntity[]> = {}; + json.forEach(pathology => { + pathologiesDatasets[pathology.code] = pathology.datasets; + }); + + return pathologiesDatasets; + }; } diff --git a/api/src/engine/engine.interfaces.ts b/api/src/engine/engine.interfaces.ts index 22f4a540d36de9b4d05ee98a529bac322a706d26..17db7ff043697a125051bdfa5791357687d3a406 100644 --- a/api/src/engine/engine.interfaces.ts +++ b/api/src/engine/engine.interfaces.ts @@ -1,5 +1,6 @@ import { Request } from 'express'; import { Observable } from 'rxjs'; +import { Domain } from './models/domain.model'; export interface IEngineOptions { type: string; @@ -9,6 +10,8 @@ export interface IEngineOptions { export interface IEngineService { demo(): string; + getDomain(): Domain[] | Promise<Domain[]>; + getAlgorithms(request: Request): Observable<string>; getExperiments(request: Request): Observable<string>; diff --git a/api/src/engine/engine.resolver.ts b/api/src/engine/engine.resolver.ts index 0e4687ca615da00101d0766b44fb7c3871e947b3..6adcf0d143a37d0960ea6dbe8d71338f32bff874 100644 --- a/api/src/engine/engine.resolver.ts +++ b/api/src/engine/engine.resolver.ts @@ -8,19 +8,10 @@ import { Domain } from './models/domain.model'; export class EngineResolver { constructor( @Inject(ENGINE_SERVICE) private readonly engineService: IEngineService, - ) {} + ) { } - @Query(() => Domain) - async hello() { - const dummy: Domain = { - id: 'test', - label: 'test', - description: 'test', - groups: [], - variables: [], - datasets: [], - }; - - return dummy; + @Query(() => [Domain]) + async domain() { + return this.engineService.getDomain(); } }