import { LayerConfigJson } from "./Json/LayerConfigJson" export interface LevelInfo { ids: string[], loop?: boolean } export class LayerConfigDependencyGraph { /** * Calculates the dependencies for the given layer * @param layerconfig */ public static getLayerImports(layerconfig: LayerConfigJson): string[] { const defaultImports: ReadonlyArray = ["questions", "filters","icons"] if (defaultImports.indexOf(layerconfig.id) >= 0) { return [] } const importedTrs: string[] = [] for (const tr of layerconfig.tagRenderings ?? []) { if (typeof tr === "string") { importedTrs.push(tr) } else if (tr["builtin"] !== undefined) { const builtin = tr["builtin"] if (typeof builtin === "string") { importedTrs.push(builtin) } else { importedTrs.push(...builtin) } } } const imports = new Set(defaultImports) for (const importValue of importedTrs) { if (importValue.indexOf(".") < 0) { continue } const [layer, _] = importValue.split(".") imports.add(layer) } return Array.from(imports) } public static buildDirectDependencies(layers: LayerConfigJson[]) { const dependsOn = new Map() for (const layer of layers) { const layerDependsOn = LayerConfigDependencyGraph.getLayerImports(layer) dependsOn.set(layer.id, layerDependsOn) } return dependsOn } public static buildLevels(dependsOn: Map): LevelInfo[]{ const levels: LevelInfo[] = [] const seenIds = new Set() while (Array.from(dependsOn.keys()).length > 0) { const currentLevel: LevelInfo = { ids: [], } levels.push(currentLevel) for (const layerId of dependsOn.keys()) { const dependencies = dependsOn.get(layerId) if (dependencies.length === 0) { currentLevel.ids.push(layerId) seenIds.add(layerId) } } const newDependsOn = new Map() for (const layerId of dependsOn.keys()) { if (seenIds.has(layerId)) { continue } const dependencies = dependsOn.get(layerId) newDependsOn.set(layerId, dependencies.filter(d => !seenIds.has(d))) } const oldSize = dependsOn.size if(oldSize === newDependsOn.size){ // We detected a loop. currentLevel.loop = true const allLayers =Array.from(newDependsOn.keys()) currentLevel.ids.push(...allLayers ) allLayers.forEach(l => seenIds.add(l)) } dependsOn = newDependsOn } return levels } }