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