| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { UIEventSource } from "../../UIEventSource" | 
					
						
							|  |  |  | import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" | 
					
						
							|  |  |  | import FilteredLayer from "../../../Models/FilteredLayer" | 
					
						
							|  |  |  | import { Tiles } from "../../../Models/TileRange" | 
					
						
							|  |  |  | import { BBox } from "../../BBox" | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | export default class FeatureSourceMerger | 
					
						
							|  |  |  |     implements FeatureSourceForLayer, Tiled, IndexedFeatureSource | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< | 
					
						
							|  |  |  |         { feature: any; freshness: Date }[] | 
					
						
							|  |  |  |     >([]) | 
					
						
							|  |  |  |     public readonly name | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |     public readonly layer: FilteredLayer | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly tileIndex: number | 
					
						
							|  |  |  |     public readonly bbox: BBox | 
					
						
							|  |  |  |     public readonly containedIds: UIEventSource<Set<string>> = new UIEventSource<Set<string>>( | 
					
						
							|  |  |  |         new Set() | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     private readonly _sources: UIEventSource<FeatureSource[]> | 
					
						
							| 
									
										
										
										
											2022-06-21 22:55:48 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Merges features from different featureSources for a single layer | 
					
						
							|  |  |  |      * Uses the freshest feature available in the case multiple sources offer data with the same identifier | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         layer: FilteredLayer, | 
					
						
							|  |  |  |         tileIndex: number, | 
					
						
							|  |  |  |         bbox: BBox, | 
					
						
							|  |  |  |         sources: UIEventSource<FeatureSource[]> | 
					
						
							|  |  |  |     ) { | 
					
						
							|  |  |  |         this.tileIndex = tileIndex | 
					
						
							|  |  |  |         this.bbox = bbox | 
					
						
							|  |  |  |         this._sources = sources | 
					
						
							|  |  |  |         this.layer = layer | 
					
						
							|  |  |  |         this.name = | 
					
						
							|  |  |  |             "FeatureSourceMerger(" + | 
					
						
							|  |  |  |             layer.layerDef.id + | 
					
						
							|  |  |  |             ", " + | 
					
						
							|  |  |  |             Tiles.tile_from_index(tileIndex).join(",") + | 
					
						
							|  |  |  |             ")" | 
					
						
							|  |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const handledSources = new Set<FeatureSource>() | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         sources.addCallbackAndRunD((sources) => { | 
					
						
							|  |  |  |             let newSourceRegistered = false | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             for (let i = 0; i < sources.length; i++) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 let source = sources[i] | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 if (handledSources.has(source)) { | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 handledSources.add(source) | 
					
						
							|  |  |  |                 newSourceRegistered = true | 
					
						
							|  |  |  |                 source.features.addCallback(() => { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     self.Update() | 
					
						
							|  |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 if (newSourceRegistered) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     self.Update() | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private Update() { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let somethingChanged = false | 
					
						
							|  |  |  |         const all: Map<string, { feature: any; freshness: Date }> = new Map< | 
					
						
							|  |  |  |             string, | 
					
						
							|  |  |  |             { feature: any; freshness: Date } | 
					
						
							|  |  |  |         >() | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |         // We seed the dictionary with the previously loaded features
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const oldValues = this.features.data ?? [] | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |         for (const oldValue of oldValues) { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |             all.set(oldValue.feature.id, oldValue) | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         for (const source of this._sources.data) { | 
					
						
							| 
									
										
										
										
											2021-04-23 12:55:38 +02:00
										 |  |  |             if (source?.features?.data === undefined) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-01-04 22:59:11 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |             for (const f of source.features.data) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const id = f.feature.properties.id | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |                 if (!all.has(id)) { | 
					
						
							|  |  |  |                     // This is a new feature
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     somethingChanged = true | 
					
						
							|  |  |  |                     all.set(id, f) | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // This value has been seen already, either in a previous run or by a previous datasource
 | 
					
						
							|  |  |  |                 // Let's figure out if something changed
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 const oldV = all.get(id) | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |                 if (oldV.freshness < f.freshness) { | 
					
						
							|  |  |  |                     // Jup, this feature is fresher
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     all.set(id, f) | 
					
						
							|  |  |  |                     somethingChanged = true | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!somethingChanged) { | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |             // We don't bother triggering an update
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-09 00:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const newList = [] | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         all.forEach((value, _) => { | 
					
						
							| 
									
										
										
										
											2021-05-07 01:43:32 +02:00
										 |  |  |             newList.push(value) | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |         this.containedIds.setData(new Set(all.keys())) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.features.setData(newList) | 
					
						
							| 
									
										
										
										
											2021-01-03 03:09:52 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |