forked from MapComplete/MapComplete
91 lines
3.1 KiB
TypeScript
91 lines
3.1 KiB
TypeScript
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<string> = ["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 = <string | string[]>tr["builtin"]
|
|
if (typeof builtin === "string") {
|
|
importedTrs.push(builtin)
|
|
} else {
|
|
importedTrs.push(...builtin)
|
|
}
|
|
}
|
|
}
|
|
|
|
const imports = new Set<string>(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<string, string[]>()
|
|
for (const layer of layers) {
|
|
const layerDependsOn = LayerConfigDependencyGraph.getLayerImports(layer)
|
|
dependsOn.set(layer.id, layerDependsOn)
|
|
}
|
|
return dependsOn
|
|
}
|
|
public static buildLevels(dependsOn: Map<string, string[]>): LevelInfo[]{
|
|
|
|
const levels: LevelInfo[] = []
|
|
const seenIds = new Set<string>()
|
|
while (Array.from(dependsOn.keys()).length > 0) {
|
|
const currentLevel: LevelInfo = {
|
|
ids: <string[]>[],
|
|
}
|
|
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<string, string[]>()
|
|
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
|
|
|
|
}
|
|
}
|