From 686b44fe98b2f92a257fb45db23b5c8d5f505c4e Mon Sep 17 00:00:00 2001 From: AlexNRCan Date: Fri, 26 Apr 2024 14:13:15 -0400 Subject: [PATCH] Start Progress Regrouped the obsolete functions --- .../legend-event-processor.ts | 4 +- .../add-new-layer/add-new-layer.tsx | 22 +- .../validation-classes/config-base-class.ts | 9 +- .../geoview-layers/abstract-geoview-layers.ts | 1138 +++++++++-------- .../layer/geoview-layers/esri-layer-common.ts | 30 +- .../geoview-layers/raster/esri-dynamic.ts | 18 +- .../layer/geoview-layers/raster/esri-image.ts | 13 +- .../geoview-layers/raster/image-static.ts | 18 +- .../geoview-layers/raster/vector-tiles.ts | 20 +- .../geo/layer/geoview-layers/raster/wms.ts | 34 +- .../layer/geoview-layers/raster/xyz-tiles.ts | 14 +- .../vector/abstract-geoview-vector.ts | 6 +- .../geo/layer/geoview-layers/vector/csv.ts | 13 +- .../geoview-layers/vector/esri-feature.ts | 11 +- .../layer/geoview-layers/vector/geojson.ts | 12 +- .../layer/geoview-layers/vector/geopackage.ts | 33 +- .../geoview-layers/vector/ogc-feature.ts | 18 +- .../geo/layer/geoview-layers/vector/wfs.ts | 23 +- .../geo/layer/layer-sets/legends-layer-set.ts | 4 - packages/geoview-core/src/geo/layer/layer.ts | 18 +- .../src/geo/map/map-schema-types.ts | 3 +- .../geoview-core/src/geo/map/map-viewer.ts | 6 +- packages/geoview-time-slider/src/index.tsx | 14 +- 23 files changed, 770 insertions(+), 711 deletions(-) diff --git a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts index 18059f7a7cf..619fee66be0 100644 --- a/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts +++ b/packages/geoview-core/src/api/event-processors/event-processor-children/legend-event-processor.ts @@ -216,7 +216,9 @@ export class LegendEventProcessor extends AbstractEventProcessor { const myLayer = MapEventProcessor.getMapViewerLayerAPI(mapId).geoviewLayers[layerPathNodes[0]]; // TODO: calculateBounds issue will be tackle ASAP in a next PR - newLegendLayer.bounds = myLayer.allLayerStatusAreGreaterThanOrEqualTo('loaded') ? myLayer.calculateBounds(layerPath) : undefined; + newLegendLayer.bounds = myLayer.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('loaded') + ? myLayer.calculateBounds(layerPath) + : undefined; } }; diff --git a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx index e8dc235e09c..52dc0cd1662 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx @@ -247,7 +247,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. wmsGeoviewLayerConfig.geoviewLayerId = wmsGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(wmsGeoviewLayerInstance); - await wmsGeoviewLayerInstance.createGeoViewLayers(); + await wmsGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); if (!wmsGeoviewLayerInstance.metadata) throw new Error('Cannot get metadata'); setHasMetadata(true); const wmsMetadata = wmsGeoviewLayerInstance.metadata; @@ -320,7 +320,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. wfsGeoviewLayerConfig.geoviewLayerId = wfsGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(wfsGeoviewLayerInstance); - await wfsGeoviewLayerInstance.createGeoViewLayers(); + await wfsGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); if (!wfsGeoviewLayerInstance.metadata) throw new Error('Cannot get metadata'); setHasMetadata(true); const wfsMetadata = wfsGeoviewLayerInstance.metadata; @@ -363,7 +363,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. ogcFeatureGeoviewLayerConfig.geoviewLayerId = ogcFeatureInstance.geoviewLayerId; setGeoviewLayerInstance(ogcFeatureInstance); - await ogcFeatureInstance.createGeoViewLayers(); + await ogcFeatureInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); const ogcFeatureMetadata = ogcFeatureInstance.metadata!; if (!ogcFeatureInstance.metadata) throw new Error('Cannot get metadata'); setHasMetadata(true); @@ -469,7 +469,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. esriGeoviewLayerConfig.geoviewLayerId = esriGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(esriGeoviewLayerInstance); - await esriGeoviewLayerInstance.createGeoViewLayers(); + await esriGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); const esriMetadata = esriGeoviewLayerInstance.metadata!; if (!esriMetadata) throw new Error('Cannot get metadata'); setHasMetadata(true); @@ -539,7 +539,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. esriImageGeoviewLayerConfig.geoviewLayerId = esriImageGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(esriImageGeoviewLayerInstance); - await esriImageGeoviewLayerInstance.createGeoViewLayers(); + await esriImageGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); const layers = [ new EsriImageLayerEntryConfig({ geoviewLayerConfig: esriImageGeoviewLayerConfig, @@ -583,7 +583,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. xyzGeoviewLayerConfig.geoviewLayerId = xyzGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(xyzGeoviewLayerInstance); - await xyzGeoviewLayerInstance.createGeoViewLayers(); + await xyzGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); setHasMetadata(false); const layers = [ new XYZTilesLayerEntryConfig({ @@ -621,7 +621,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. csvGeoviewLayerConfig.geoviewLayerId = csvGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(csvGeoviewLayerInstance); - await csvGeoviewLayerInstance.createGeoViewLayers(); + await csvGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); const layers = [ new CsvLayerEntryConfig({ geoviewLayerConfig: csvGeoviewLayerConfig, @@ -662,7 +662,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. geojsonGeoviewLayerConfig.geoviewLayerId = geojsonGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(geojsonGeoviewLayerInstance); - await geojsonGeoviewLayerInstance.createGeoViewLayers(); + await geojsonGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); setHasMetadata(true); if (!geojsonGeoviewLayerInstance.metadata) throw new Error('Cannot get metadata'); const geojsonFeatureMetadata = geojsonGeoviewLayerInstance.metadata!; @@ -687,7 +687,7 @@ export function AddNewLayer(): JSX.Element { // Synchronize the geoviewLayerId. geojsonGeoviewLayerConfig.geoviewLayerId = geojsonGeoviewLayerInstance.geoviewLayerId; setGeoviewLayerInstance(geojsonGeoviewLayerInstance); - await geojsonGeoviewLayerInstance.createGeoViewLayers(); + await geojsonGeoviewLayerInstance.obsoleteConfigAndLayerCreateGeoViewLayers(); const layers = [ new GeoJSONLayerEntryConfig({ geoviewLayerConfig: geojsonGeoviewLayerConfig, @@ -849,9 +849,9 @@ export function AddNewLayer(): JSX.Element { }; const doneAddedShowMessage = (layerBeingAdded: AbstractGeoViewLayer): void => { - if (layerBeingAdded.allLayerStatusAreGreaterThanOrEqualTo('error')) + if (layerBeingAdded.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('error')) api.maps[mapId].notifications.showMessage('layers.layerAddedWithError', [layerName]); - else if (layerBeingAdded?.allLayerStatusAreGreaterThanOrEqualTo('loaded')) + else if (layerBeingAdded?.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('loaded')) api.maps[mapId].notifications.showMessage('layers.layerAdded', [layerName]); else api.maps[mapId].notifications.showMessage('layers.layerAddedAndLoading', [layerName]); }; diff --git a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts index 30fe9677a65..0275b0039dc 100644 --- a/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts +++ b/packages/geoview-core/src/core/utils/config/validation-classes/config-base-class.ts @@ -173,7 +173,9 @@ export class ConfigBaseClass { // eslint-disable-next-line no-underscore-dangle this._layerStatus === 'loaded' && this.parentLayerConfig && - this.geoviewLayerInstance!.allLayerStatusAreGreaterThanOrEqualTo('loaded', [this.parentLayerConfig as GroupLayerEntryConfig]) + this.geoviewLayerInstance!.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('loaded', [ + this.parentLayerConfig as GroupLayerEntryConfig, + ]) ) (this.parentLayerConfig as GroupLayerEntryConfig).layerStatus = 'loaded'; } @@ -183,9 +185,6 @@ export class ConfigBaseClass { * @param {LayerStatusChangedEvent} event The event to emit * @private */ - // TODO: refactor - if this emit is privare with #, abstract-base-layer-entry-config.ts:28 Uncaught (in promise) TypeError: Private element is not present on this object - // TD.CONT: this by pass the error, I need to set this public. The problem come from the groupLayer object trying to emit this event but - // TD.CONT: the event is not define so this.onLayerStatus.... failed #emitLayerStatusChanged(event: LayerStatusChangedEvent): void { // Emit the event for all handlers EventHelper.emitEvent(this, this.#onLayerStatusChangedHandlers, event); @@ -222,7 +221,7 @@ export class ConfigBaseClass { // TODO: Check - Move this registerToLayerSets closer to the others, when I comment the line it seems good, except // TO.DOCONT: for an 'Anonymous' group layer that never got 'loaded'. See if we can fix this elsewhere and remove this. if (this.entryType !== CONST_LAYER_ENTRY_TYPES.GROUP) - (this.geoviewLayerInstance as AbstractGeoViewLayer).registerToLayerSets(Cast(this)); + (this.geoviewLayerInstance as AbstractGeoViewLayer).obsoleteLayerAPIRegisterToLayerSets(Cast(this)); this.layerStatus = 'registered'; return true; diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts b/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts index 7ad4660a84b..0234e0f9b16 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/abstract-geoview-layers.ts @@ -112,7 +112,7 @@ export abstract class AbstractGeoViewLayer { layerMetadata: Record = {}; /** Layer temporal dimension indexed by layerPath. */ - layerTemporalDimension: Record = {}; + #obsoleteConfigLayerTemporalDimension: Record = {}; /** Attribution used in the OpenLayer source. */ attributions: string[] = []; @@ -155,33 +155,7 @@ export abstract class AbstractGeoViewLayer { ? DateMgt.getDateFragmentsOrder(mapLayerConfig.serviceDateFormat) : undefined; this.externalFragmentsOrder = DateMgt.getDateFragmentsOrder(mapLayerConfig.externalDateFormat); - this.setListOfLayerEntryConfig(mapLayerConfig, mapLayerConfig.listOfLayerEntryConfig); - } - - /** *************************************************************************************************************************** - * Set the list of layer entry configuration and initialize the registered layer object and register all layers to layer sets. - * - * @param {TypeGeoviewLayer} mapLayerConfig The GeoView layer configuration options. - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration - */ - private setListOfLayerEntryConfig(mapLayerConfig: TypeGeoviewLayerConfig, listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { - if (listOfLayerEntryConfig.length === 0) return; - if (listOfLayerEntryConfig.length === 1) this.listOfLayerEntryConfig = listOfLayerEntryConfig; - else { - const layerGroup = new GroupLayerEntryConfig({ - geoviewLayerConfig: listOfLayerEntryConfig[0].geoviewLayerConfig, - layerId: this.geoviewLayerId, - layerName: this.geoviewLayerName, - isMetadataLayerGroup: false, - initialSettings: mapLayerConfig.initialSettings, - listOfLayerEntryConfig, - } as GroupLayerEntryConfig); - this.listOfLayerEntryConfig = [layerGroup]; - layerGroup.listOfLayerEntryConfig.forEach((layerConfig, i) => { - (layerGroup.listOfLayerEntryConfig[i] as AbstractBaseLayerEntryConfig).parentLayerConfig = layerGroup; - }); - } - this.listOfLayerEntryConfig[0].geoviewLayerConfig.listOfLayerEntryConfig = listOfLayerEntryConfig; + this.#obsoleteConfigSetListOfLayerEntryConfig(mapLayerConfig, mapLayerConfig.listOfLayerEntryConfig); } /** @@ -296,27 +270,6 @@ export abstract class AbstractGeoViewLayer { EventHelper.offEvent(this.#onVisibleChangedHandlers, callback); } - /** *************************************************************************************************************************** - * Process recursively the list of layer entries to see if all of them are processed. - * - * @param {TypeLayerStatus} layerStatus The layer status to compare with the internal value of the config. - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration - * (default: this.listOfLayerEntryConfig). - * - * @returns {boolean} true when all layers are greater than or equal to the layerStatus parameter. - */ - allLayerStatusAreGreaterThanOrEqualTo( - layerStatus: TypeLayerStatus, - listOfLayerEntryConfig: TypeListOfLayerEntryConfig = this.listOfLayerEntryConfig - ): boolean { - // Try to find a layer that is not greater than or equal to the layerStatus parameter. If you can, return false - return !listOfLayerEntryConfig.find((layerConfig: TypeLayerEntryConfig) => { - if (layerEntryIsGroupLayer(layerConfig)) - return !this.allLayerStatusAreGreaterThanOrEqualTo(layerStatus, layerConfig.listOfLayerEntryConfig); - return !layerConfig.IsGreaterThanOrEqualTo(layerStatus || 'newInstance'); - }); - } - /** *************************************************************************************************************************** * Recursively process the list of layer entries to count all layers in error. * @@ -334,472 +287,148 @@ export abstract class AbstractGeoViewLayer { } /** *************************************************************************************************************************** - * Process recursively the list of layer entries to initialize the registeredLayers object. + * Return feature information for the layer specified. * - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries to process. - */ - initRegisteredLayers(layerApi: LayerApi, listOfLayerEntryConfig: TypeListOfLayerEntryConfig = this.listOfLayerEntryConfig): void { - listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig, i) => { - if (layerApi.isRegistered(layerConfig)) { - this.layerLoadError.push({ - layer: layerConfig.layerPath, - loggerMessage: `Duplicate layerPath (mapId: ${this.mapId}, layerPath: ${layerConfig.layerPath})`, - }); - // Duplicat layer can't be kept because it has the same layer path than the first encontered layer. - delete listOfLayerEntryConfig[i]; - } else { - layerConfig.geoviewLayerInstance = this; - layerConfig.registerLayerConfig(); - } - if (layerEntryIsGroupLayer(layerConfig)) this.initRegisteredLayers(layerApi, layerConfig.listOfLayerEntryConfig); - }); - } - - /** *************************************************************************************************************************** - * This method is used to create the layers specified in the listOfLayerEntryConfig attribute inherited from its parent. - * Normally, it is the second method called in the life cycle of a GeoView layer, the first one being the constructor. - * Its code is the same for all child classes. It must first validate that the olLayers attribute is null indicating - * that the method has never been called before for this layer. If this is not the case, an error message must be sent. - * Then, it calls the abstract method getAdditionalServiceDefinition. For example, when the child is a WFS service, this - * method executes the GetCapabilities request and saves the result in the metadata attribute of the class. It also process - * the layer's metadata for each layer in the listOfLayerEntryConfig tree in order to define the missing pieces of the layer's - * configuration. Layer's configuration can come from the configuration of the GeoView layer or from the information saved by - * the method processListOfLayerEntryMetadata, priority being given to the first of the two. When the GeoView layer does not - * have a service definition, the getAdditionalServiceDefinition method does nothing. + * @param {QueryType} queryType The type of query to perform. + * @param {string} layerPath The layer path to the layer's configuration. + * @param {TypeLocation} location An optionsl pixel, coordinate or polygon that will be used by the query. * - * Finally, the processListOfLayerEntryConfig is called to instantiate each layer identified by the listOfLayerEntryConfig - * attribute. This method will also register the layers to all layer sets that offer this possibility. For example, if a layer - * is queryable, it will subscribe to the details-panel and every time the user clicks on the map, the panel will ask the layer - * to return the descriptive information of all the features in a tolerance radius. This information will be used to populate - * the details-panel. + * @returns {Promise} The feature info table. */ - async createGeoViewLayers(): Promise { - if (this.olLayers === null) { - // Log - logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - createGeoViewLayers', this.listOfLayerEntryConfig); + // GV Things important to know about the get feature info family of methods + /* + * There's no doubt that the layerConfig is correctly defined when we call these methods. The layerConfig object is created in + * the GeoView layer constructor and has all the necessary flags to inform programmers and users whether the layer referenced by + * a layerConfig or its layerPath is viable or not. If the layer is not visible on the map, it has probably not yet been loaded + * or an error has occurred. If clicked on, these layers will return an empty array, as they have no features on the map. So + * users can't expect anything to be returned after a click. They have to wait until they see something on the map to know where + * the features are so they can click on them. + */ + async getFeatureInfo( + queryType: QueryType, + layerPath: string, + location: TypeLocation = null + ): Promise { + try { + // TODO: Refactor - Rework this function to not need a layer path in the param, nor a need to get a layer config here.. + // TO.DOCONT: For example, this call seems to have logic redundancy: `layerConfig.geoviewLayerInstance.getFeatureInfo(queryType, layerPath, location)` + // Get the layer config + const layerConfig = this.getLayerConfig(layerPath); - // Try to get a key for logging timings - let logTimingsKey; - if (this.listOfLayerEntryConfig.length > 0) logTimingsKey = `${this.mapId} | ${this.listOfLayerEntryConfig[0].layerPath}`; + if (!layerConfig || !layerConfig?.source?.featureInfo?.queryable) { + logger.logError('Invalid usage of getFeatureInfo\nlayerConfig = ', layerConfig); + const queryableOrNot = layerConfig?.source?.featureInfo?.queryable ? '' : 'not'; + logger.logError(`Layer is ${queryableOrNot} queryable`); + return null; + } // Log - if (logTimingsKey) logger.logMarkerStart(logTimingsKey); + logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - getFeatureInfo', queryType, layerPath); + const logMarkerKey = `${queryType} | ${layerPath}`; + logger.logMarkerStart(logMarkerKey); - // Get additional service and await - await this.getAdditionalServiceDefinition(); + let promiseGetFeature: Promise; + switch (queryType) { + case 'all': + promiseGetFeature = this.getAllFeatureInfo(layerPath); + break; + case 'at_pixel': + promiseGetFeature = this.getFeatureInfoAtPixel(location as Pixel, layerPath); + break; + case 'at_coordinate': + promiseGetFeature = this.getFeatureInfoAtCoordinate(location as Coordinate, layerPath); + break; + case 'at_long_lat': + promiseGetFeature = this.getFeatureInfoAtLongLat(location as Coordinate, layerPath); + break; + case 'using_a_bounding_box': + promiseGetFeature = this.getFeatureInfoUsingBBox(location as Coordinate[], layerPath); + break; + case 'using_a_polygon': + promiseGetFeature = this.getFeatureInfoUsingPolygon(location as Coordinate[], layerPath); + break; + default: + // Default is empty array + promiseGetFeature = Promise.resolve([]); - // Log the time it took thus far - if (logTimingsKey) logger.logMarkerCheck(logTimingsKey, 'to get additional service definition'); + // Log + logger.logWarning(`Queries using ${queryType} are invalid.`); + break; + } - // Process list of layers and await - this.olLayers = await this.processListOfLayerEntryConfig(this.listOfLayerEntryConfig); + // Wait for results + const arrayOfFeatureInfoEntries = await promiseGetFeature; - // Log the time it took thus far - if (logTimingsKey) logger.logMarkerCheck(logTimingsKey, 'to process list of layer entry config'); - } else { - // Raise error - throw new GeoViewLayerCreatedTwiceError(this, this.mapId); - } - } + // Log + logger.logMarkerCheck(logMarkerKey, 'to getFeatureInfo', arrayOfFeatureInfoEntries); - /** *************************************************************************************************************************** - * This method reads from the metadataAccessPath additional information to complete the GeoView layer configuration. - */ - protected async getAdditionalServiceDefinition(): Promise { - try { - await this.fetchServiceMetadata(); - if (this.listOfLayerEntryConfig.length) await this.validateAndExtractLayerMetadata(); + // Return the result + return arrayOfFeatureInfoEntries; } catch (error) { // Log logger.logError(error); + return null; } } /** *************************************************************************************************************************** - * This method Validate the list of layer configs and extract them in the geoview instance. + * Return feature information for all the features on a layer. Returns an empty array [] when the layer is + * not queryable. + * + * @param {string} layerPath The layer path to the layer's configuration. + * + * @returns {Promise} The feature info table. */ - async validateAndExtractLayerMetadata(): Promise { - try { - // Recursively process the configuration tree of layer entries by removing layers in error and processing valid layers. - this.validateListOfLayerEntryConfig(this.listOfLayerEntryConfig); - await this.processListOfLayerEntryMetadata(this.listOfLayerEntryConfig); - } catch (error) { - // Log - logger.logError(error); - } + // Added eslint-disable here, because we do want to override this method in children and keep 'this'. + // eslint-disable-next-line @typescript-eslint/class-methods-use-this + protected getAllFeatureInfo(layerPath: string): Promise { + // Log + logger.logError(`getAllFeatureInfo is not implemented! for ${layerPath}`); + return Promise.resolve(null); } /** *************************************************************************************************************************** - * This method reads the service metadata from the metadataAccessPath. + * Return feature information for all the features around the provided Pixel. Returns an empty array [] when the layer is + * not queryable. * - * @returns {Promise} A promise that the execution is completed. + * @param {Coordinate} location The pixel coordinate that will be used by the query. + * @param {string} layerPath The layer path to the layer's configuration. + * + * @returns {Promise} The feature info table. */ - protected async fetchServiceMetadata(): Promise { - const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); - if (metadataUrl) { - try { - const metadataString = await getXMLHttpRequest(`${metadataUrl}?f=json`); - if (metadataString === '{}') this.metadata = null; - else { - this.metadata = toJsonObject(JSON.parse(metadataString)); - const { copyrightText } = this.metadata; - if (copyrightText) this.attributions.push(copyrightText as string); - } - } catch (error) { - // Log - logger.logError(error); - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); - } - } + // Added eslint-disable here, because we do want to override this method in children and keep 'this'. + // eslint-disable-next-line @typescript-eslint/class-methods-use-this + protected getFeatureInfoAtPixel(location: Pixel, layerPath: string): Promise { + // Log + logger.logError(`getFeatureInfoAtPixel is not implemented! for ${layerPath} - ${location}`); + return Promise.resolve(null); } /** *************************************************************************************************************************** - * This method recursively validates the configuration of the layer entries to ensure that each layer is correctly defined. If - * necessary, additional code can be executed in the child method to complete the layer configuration. + * Return feature information for all the features around the provided coordinate. Returns an empty array [] when the layer is + * not queryable. * - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. + * @param {Coordinate} location The coordinate that will be used by the query. + * @param {string} layerPath The layer path to the layer's configuration. + * + * @returns {Promise} The feature info table. */ - protected abstract validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void; + // Added eslint-disable here, because we do want to override this method in children and keep 'this'. + // eslint-disable-next-line @typescript-eslint/class-methods-use-this + protected getFeatureInfoAtCoordinate(location: Coordinate, layerPath: string): Promise { + // Log + logger.logError(`getFeatureInfoAtCoordinate is not implemented! for ${layerPath} - ${location}`); + return Promise.resolve(null); + } /** *************************************************************************************************************************** - * This method processes recursively the metadata of each layer in the "layer list" configuration. + * Return feature information for all the features around the provided longitude latitude. Returns an empty array [] when the + * layer is not queryable. * - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layers to process. + * @param {Coordinate} location The coordinate that will be used by the query. + * @param {string} layerPath The layer path to the layer's configuration. * - * @returns {Promise} A promise that the execution is completed. - */ - protected async processListOfLayerEntryMetadata(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): Promise { - try { - const promisedAllLayerDone: Promise[] = []; - for (let i = 0; i < listOfLayerEntryConfig.length; i++) { - const layerConfig: TypeLayerEntryConfig = listOfLayerEntryConfig[i]; - if (layerEntryIsGroupLayer(layerConfig)) - if (layerConfig.isMetadataLayerGroup) promisedAllLayerDone.push(this.processMetadataGroupLayer(layerConfig)); - // eslint-disable-next-line no-await-in-loop - else await this.processListOfLayerEntryMetadata(layerConfig.listOfLayerEntryConfig); - else promisedAllLayerDone.push(this.processLayerMetadata(layerConfig)); - } - const arrayOfLayerConfigs = await Promise.all(promisedAllLayerDone); - arrayOfLayerConfigs.forEach((layerConfig) => { - if (layerConfig.layerStatus === 'error') { - const message = `Error while loading layer path "${layerConfig.layerPath})" on map "${this.mapId}"`; - this.layerLoadError.push({ layer: layerConfig.layerPath, loggerMessage: message }); - throw new Error(message); - } else { - // When we get here, we know that the metadata (if the service provide some) are processed. - // We need to signal to the layer sets that the 'processed' phase is done. - // GV TODO: For the moment, be aware that the layerStatus setter is doing a lot of things behind the scene. - // GV The layerStatus setter contains a lot of code and we will change it in favor of a method. - layerConfig.layerStatus = 'processed'; - } - }); - } catch (error) { - // Log - logger.logError(error); - } - } - - /** *************************************************************************************************************************** - * This method is used to process metadata group layer entries. These layers behave as a GeoView group layer and also as a data - * layer (i.e. they have extent, visibility and query flag definition). Metadata group layers can be identified by - * the presence of an isMetadataLayerGroup attribute set to true. - * - * @param {GroupLayerEntryConfig} layerConfig The layer entry configuration to process. - * - * @returns {Promise} A promise that the vector layer configuration has its metadata and group layers processed. - */ - private async processMetadataGroupLayer(layerConfig: GroupLayerEntryConfig): Promise { - try { - await this.processLayerMetadata(layerConfig); - await this.processListOfLayerEntryMetadata(layerConfig.listOfLayerEntryConfig!); - layerConfig.layerStatus = 'processed'; - return layerConfig; - } catch (error) { - // Log - logger.logError(error); - } - return layerConfig; - } - - /** *************************************************************************************************************************** - * This method is used to process the layer's metadata. It will fill the empty outfields and aliasFields properties of the - * layer's configuration when applicable. - * - * @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process. - * - * @returns {Promise} A promise that the vector layer configuration has its metadata processed. - */ - // Added eslint-disable here, because we do want to override this method in children and keep 'this'. - // eslint-disable-next-line @typescript-eslint/class-methods-use-this - protected processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { - if (!layerConfig.source) layerConfig.source = {}; - if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: false }; - - return Promise.resolve(layerConfig); - } - - /** *************************************************************************************************************************** - * Process recursively the list of layer Entries to create the layers and the layer groups. - * - * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries to process. - * @param {LayerGroup} layerGroup Optional layer group to use when we have many layers. The very first call to - * processListOfLayerEntryConfig must not provide a value for this parameter. It is defined for internal use. - * - * @returns {Promise} The promise that the layers were processed. - */ - async processListOfLayerEntryConfig( - listOfLayerEntryConfig: TypeListOfLayerEntryConfig, - layerGroup?: LayerGroup - ): Promise { - // Log - logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - processListOfLayerEntryConfig', listOfLayerEntryConfig); - - try { - if (listOfLayerEntryConfig.length === 0) return null; - if (listOfLayerEntryConfig.length === 1) { - if (layerEntryIsGroupLayer(listOfLayerEntryConfig[0])) { - const newLayerGroup = AbstractGeoViewLayer.createLayerGroup( - listOfLayerEntryConfig[0], - listOfLayerEntryConfig[0].initialSettings! - ); - const groupReturned = await this.processListOfLayerEntryConfig(listOfLayerEntryConfig[0].listOfLayerEntryConfig!, newLayerGroup); - if (groupReturned) { - if (layerGroup) layerGroup.getLayers().push(groupReturned); - return groupReturned; - } - this.layerLoadError.push({ - layer: listOfLayerEntryConfig[0].layerPath, - loggerMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`, - }); - return null; - } - - if ((listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig).layerStatus === 'error') return null; - const { layerPath } = listOfLayerEntryConfig[0]; - const baseLayer = await this.processOneLayerEntry(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig); - if (baseLayer) { - this.registerToLayerSets(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig); - if (layerGroup) layerGroup!.getLayers().push(baseLayer!); - return layerGroup || baseLayer; - } - this.layerLoadError.push({ - layer: listOfLayerEntryConfig[0].layerPath, - loggerMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`, - }); - this.getLayerConfig(layerPath)!.layerStatus = 'error'; - return null; - } - - if (!layerGroup) { - // All children of this level in the tree have the same parent, so we use the first element of the array to retrieve the parent node. - layerGroup = AbstractGeoViewLayer.createLayerGroup( - (listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig).parentLayerConfig as TypeLayerEntryConfig, - listOfLayerEntryConfig[0].initialSettings! - ); - } - const promiseOfLayerCreated: Promise[] = []; - listOfLayerEntryConfig.forEach((layerConfig, i) => { - if (layerEntryIsGroupLayer(layerConfig)) { - const newLayerGroup = AbstractGeoViewLayer.createLayerGroup( - listOfLayerEntryConfig[i], - listOfLayerEntryConfig[i].initialSettings! - ); - promiseOfLayerCreated.push(this.processListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!, newLayerGroup)); - } else if ((listOfLayerEntryConfig[i] as AbstractBaseLayerEntryConfig).layerStatus === 'error') - promiseOfLayerCreated.push(Promise.resolve(null)); - else { - promiseOfLayerCreated.push(this.processOneLayerEntry(layerConfig as AbstractBaseLayerEntryConfig)); - } - }); - const listOfLayerCreated = await Promise.all(promiseOfLayerCreated); - listOfLayerCreated.forEach((baseLayer, i) => { - const { layerPath } = listOfLayerEntryConfig[i]; - if (baseLayer) { - const layerConfig = baseLayer?.get('layerConfig') as AbstractBaseLayerEntryConfig; - if (layerConfig) { - if (!layerEntryIsGroupLayer(listOfLayerEntryConfig[i])) { - this.registerToLayerSets(baseLayer.get('layerConfig') as AbstractBaseLayerEntryConfig); - } - layerGroup!.getLayers().push(baseLayer); - } - } else { - this.layerLoadError.push({ - layer: listOfLayerEntryConfig[i].layerPath, - loggerMessage: `Unable to create ${ - layerEntryIsGroupLayer(listOfLayerEntryConfig[i]) ? CONST_LAYER_ENTRY_TYPES.GROUP : '' - } layer ${listOfLayerEntryConfig[i].layerPath} on map ${this.mapId}`, - }); - this.getLayerConfig(layerPath)!.layerStatus = 'error'; - } - }); - - return layerGroup!; - } catch (error) { - // Log - logger.logError(error); - return null; - } - } - - /** *************************************************************************************************************************** - * This method creates a GeoView layer using the definition provided in the layerConfig parameter. - * - * @param {AbstractBaseLayerEntryConfig} layerConfig Information needed to create the GeoView layer. - * - * @returns {Promise} The GeoView layer that has been created. - */ - // Added eslint-disable here, because we do want to override this method in children and keep 'this'. - // eslint-disable-next-line @typescript-eslint/class-methods-use-this - protected processOneLayerEntry(layerConfig: AbstractBaseLayerEntryConfig): Promise { - // GV IMPORTANT: The processOneLayerEntry method of all the children must call this method to ensure that the flow of - // GV layerStatus values is correctly sequenced. - layerConfig.layerStatus = 'loading'; - return Promise.resolve(null); - } - - /** *************************************************************************************************************************** - * Return feature information for the layer specified. - * - * @param {QueryType} queryType The type of query to perform. - * @param {string} layerPath The layer path to the layer's configuration. - * @param {TypeLocation} location An optionsl pixel, coordinate or polygon that will be used by the query. - * - * @returns {Promise} The feature info table. - */ - // GV Things important to know about the get feature info family of methods - /* - * There's no doubt that the layerConfig is correctly defined when we call these methods. The layerConfig object is created in - * the GeoView layer constructor and has all the necessary flags to inform programmers and users whether the layer referenced by - * a layerConfig or its layerPath is viable or not. If the layer is not visible on the map, it has probably not yet been loaded - * or an error has occurred. If clicked on, these layers will return an empty array, as they have no features on the map. So - * users can't expect anything to be returned after a click. They have to wait until they see something on the map to know where - * the features are so they can click on them. - */ - async getFeatureInfo( - queryType: QueryType, - layerPath: string, - location: TypeLocation = null - ): Promise { - try { - // TODO: Refactor - Rework this function to not need a layer path in the param, nor a need to get a layer config here.. - // TO.DOCONT: For example, this call seems to have logic redundancy: `layerConfig.geoviewLayerInstance.getFeatureInfo(queryType, layerPath, location)` - // Get the layer config - const layerConfig = this.getLayerConfig(layerPath); - - if (!layerConfig || !layerConfig?.source?.featureInfo?.queryable) { - logger.logError('Invalid usage of getFeatureInfo\nlayerConfig = ', layerConfig); - const queryableOrNot = layerConfig?.source?.featureInfo?.queryable ? '' : 'not'; - logger.logError(`Layer is ${queryableOrNot} queryable`); - return null; - } - - // Log - logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - getFeatureInfo', queryType, layerPath); - const logMarkerKey = `${queryType} | ${layerPath}`; - logger.logMarkerStart(logMarkerKey); - - let promiseGetFeature: Promise; - switch (queryType) { - case 'all': - promiseGetFeature = this.getAllFeatureInfo(layerPath); - break; - case 'at_pixel': - promiseGetFeature = this.getFeatureInfoAtPixel(location as Pixel, layerPath); - break; - case 'at_coordinate': - promiseGetFeature = this.getFeatureInfoAtCoordinate(location as Coordinate, layerPath); - break; - case 'at_long_lat': - promiseGetFeature = this.getFeatureInfoAtLongLat(location as Coordinate, layerPath); - break; - case 'using_a_bounding_box': - promiseGetFeature = this.getFeatureInfoUsingBBox(location as Coordinate[], layerPath); - break; - case 'using_a_polygon': - promiseGetFeature = this.getFeatureInfoUsingPolygon(location as Coordinate[], layerPath); - break; - default: - // Default is empty array - promiseGetFeature = Promise.resolve([]); - - // Log - logger.logWarning(`Queries using ${queryType} are invalid.`); - break; - } - - // Wait for results - const arrayOfFeatureInfoEntries = await promiseGetFeature; - - // Log - logger.logMarkerCheck(logMarkerKey, 'to getFeatureInfo', arrayOfFeatureInfoEntries); - - // Return the result - return arrayOfFeatureInfoEntries; - } catch (error) { - // Log - logger.logError(error); - return null; - } - } - - /** *************************************************************************************************************************** - * Return feature information for all the features on a layer. Returns an empty array [] when the layer is - * not queryable. - * - * @param {string} layerPath The layer path to the layer's configuration. - * - * @returns {Promise} The feature info table. - */ - // Added eslint-disable here, because we do want to override this method in children and keep 'this'. - // eslint-disable-next-line @typescript-eslint/class-methods-use-this - protected getAllFeatureInfo(layerPath: string): Promise { - // Log - logger.logError(`getAllFeatureInfo is not implemented! for ${layerPath}`); - return Promise.resolve(null); - } - - /** *************************************************************************************************************************** - * Return feature information for all the features around the provided Pixel. Returns an empty array [] when the layer is - * not queryable. - * - * @param {Coordinate} location The pixel coordinate that will be used by the query. - * @param {string} layerPath The layer path to the layer's configuration. - * - * @returns {Promise} The feature info table. - */ - // Added eslint-disable here, because we do want to override this method in children and keep 'this'. - // eslint-disable-next-line @typescript-eslint/class-methods-use-this - protected getFeatureInfoAtPixel(location: Pixel, layerPath: string): Promise { - // Log - logger.logError(`getFeatureInfoAtPixel is not implemented! for ${layerPath} - ${location}`); - return Promise.resolve(null); - } - - /** *************************************************************************************************************************** - * Return feature information for all the features around the provided coordinate. Returns an empty array [] when the layer is - * not queryable. - * - * @param {Coordinate} location The coordinate that will be used by the query. - * @param {string} layerPath The layer path to the layer's configuration. - * - * @returns {Promise} The feature info table. - */ - // Added eslint-disable here, because we do want to override this method in children and keep 'this'. - // eslint-disable-next-line @typescript-eslint/class-methods-use-this - protected getFeatureInfoAtCoordinate(location: Coordinate, layerPath: string): Promise { - // Log - logger.logError(`getFeatureInfoAtCoordinate is not implemented! for ${layerPath} - ${location}`); - return Promise.resolve(null); - } - - /** *************************************************************************************************************************** - * Return feature information for all the features around the provided longitude latitude. Returns an empty array [] when the - * layer is not queryable. - * - * @param {Coordinate} location The coordinate that will be used by the query. - * @param {string} layerPath The layer path to the layer's configuration. - * - * @returns {Promise} The feature info table. + * @returns {Promise} The feature info table. */ // Added eslint-disable here, because we do want to override this method in children and keep 'this'. // eslint-disable-next-line @typescript-eslint/class-methods-use-this @@ -843,33 +472,6 @@ export abstract class AbstractGeoViewLayer { return Promise.resolve(null); } - /** *************************************************************************************************************************** - * This method register the layer entry to layer sets. Nothing is done if the registration is already done. - * - * @param {AbstractBaseLayerEntryConfig} layerConfig The layer config to register. - */ - registerToLayerSets(layerConfig: AbstractBaseLayerEntryConfig): void { - // TODO: Refactor - This function should be deleted eventually. It's up to the layer orchestrator to manage the layers. - // TO.DOCONT: The layer itself shouldn't know about it nor should have an explicit function mentioning the layer sets. - - // Register to layer sets that are already created. - // Emit the layer registration - this.#emitGeoViewLayerRegistration({ layerPath: layerConfig.layerPath, layerConfig, action: 'add' }); - } - - /** *************************************************************************************************************************** - * This method unregisters the layer from the layer sets. - * - * @param {AbstractBaseLayerEntryConfig} layerConfig The layer entry to register. - */ - unregisterFromLayerSets(layerConfig: AbstractBaseLayerEntryConfig): void { - // TODO: Refactor - This function should be deleted eventually. It's up to the layer orchestrator to manage the layers. - // TO.DOCONT: The layer itself shouldn't know about it nor should have an explicit function mentioning the layer sets. - - // Emit the layer unregistration - this.#emitGeoViewLayerRegistration({ layerPath: layerConfig.layerPath, layerConfig, action: 'remove' }); - } - /** * Queries the legend. * This function raises legend querying and queried events. @@ -906,7 +508,10 @@ export abstract class AbstractGeoViewLayer { * @param {TypeLayerInitialSettings } initialSettings Initial settings to apply to the layer. * @returns {LayerGroup} A new layer group. */ - protected static createLayerGroup(layerConfig: TypeLayerEntryConfig, initialSettings: TypeLayerInitialSettings): LayerGroup { + protected static obsoleteConfigCreateLayerGroup( + layerConfig: TypeLayerEntryConfig, + initialSettings: TypeLayerInitialSettings + ): LayerGroup { const layerGroupOptions: LayerGroupOptions = { layers: new Collection(), properties: { layerConfig }, @@ -1356,93 +961,497 @@ export abstract class AbstractGeoViewLayer { } catch (error) { // Log logger.logError(error); - return []; + return []; + } + } + + /** *************************************************************************************************************************** + * Get the layerFilter that is associated to the layer. Returns undefined when the layer config can't be found using the layer + * path. + * + * @param {string} layerPath The layer path to the layer's configuration. + * + * @returns {string | undefined} The filter associated to the layer or undefined. + */ + getLayerFilter(layerPath: string): string | undefined { + const layerConfig = this.getLayerConfig(layerPath); + return layerConfig?.olLayer?.get('layerFilter'); + } + + /** *************************************************************************************************************************** + * Get the layerFilter that is associated to the layer. Returns undefined when the layer config can't be found using the layer + * path. + * + * @param {string} layerPath The layer path to the layer's configuration. + * + * @returns {TimeDimension} The temporal dimension associated to the layer or undefined. + */ + getTemporalDimension(layerPath: string): TimeDimension { + return this.#obsoleteConfigLayerTemporalDimension[layerPath]; + } + + /** *************************************************************************************************************************** + * Get the bounds of the layer represented in the layerConfig pointed to by the layerPath, returns updated bounds + * + * @param {string} layerPath The Layer path to the layer's configuration. + * @param {Extent | undefined} bounds The current bounding box to be adjusted. + * + * @returns {Extent} The new layer bounding box. + */ + protected abstract getBounds(layerPath: string, bounds?: Extent): Extent | undefined; + + /** *************************************************************************************************************************** + * Compute the layer bounds or undefined if the result can not be obtained from the feature extents that compose the layer. If + * projectionCode is defined, returns the bounds in the specified projection otherwise use the map projection. The bounds are + * different from the extent. They are mainly used for display purposes to show the bounding box in which the data resides and + * to zoom in on the entire layer data. It is not used by openlayer to limit the display of data on the map. + * + * @param {string} layerPath The Layer path to the layer's configuration. + * @param {string | number | undefined} projectionCode Optional projection code to use for the returned bounds. Default to + * current projection. + * + * @returns {Extent | undefined} The layer bounding box. + */ + calculateBounds(layerPath: string): Extent | undefined { + try { + let bounds: Extent | undefined; + const processGroupLayerBounds = (listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void => { + listOfLayerEntryConfig.forEach((layerConfig) => { + if (layerEntryIsGroupLayer(layerConfig)) processGroupLayerBounds(layerConfig.listOfLayerEntryConfig); + else { + bounds = this.getBounds(layerConfig.layerPath, bounds); + } + }); + }; + + const initialLayerConfig = this.getLayerConfig(layerPath); + if (initialLayerConfig) { + if (Array.isArray(initialLayerConfig)) processGroupLayerBounds(initialLayerConfig); + else processGroupLayerBounds([initialLayerConfig]); + } + + return bounds; + } catch (error) { + // Log + logger.logError(`Couldn't calculate bounds on layer ${layerPath}`, error); + return undefined; + } + } + + /** *************************************************************************************************************************** + * Set the list of layer entry configuration and initialize the registered layer object and register all layers to layer sets. + * + * @param {TypeGeoviewLayer} mapLayerConfig The GeoView layer configuration options. + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration. + * @private + */ + #obsoleteConfigSetListOfLayerEntryConfig( + mapLayerConfig: TypeGeoviewLayerConfig, + listOfLayerEntryConfig: TypeListOfLayerEntryConfig + ): void { + if (listOfLayerEntryConfig.length === 0) return; + if (listOfLayerEntryConfig.length === 1) this.listOfLayerEntryConfig = listOfLayerEntryConfig; + else { + const layerGroup = new GroupLayerEntryConfig({ + geoviewLayerConfig: listOfLayerEntryConfig[0].geoviewLayerConfig, + layerId: this.geoviewLayerId, + layerName: this.geoviewLayerName, + isMetadataLayerGroup: false, + initialSettings: mapLayerConfig.initialSettings, + listOfLayerEntryConfig, + } as GroupLayerEntryConfig); + this.listOfLayerEntryConfig = [layerGroup]; + layerGroup.listOfLayerEntryConfig.forEach((layerConfig, i) => { + (layerGroup.listOfLayerEntryConfig[i] as AbstractBaseLayerEntryConfig).parentLayerConfig = layerGroup; + }); + } + this.listOfLayerEntryConfig[0].geoviewLayerConfig.listOfLayerEntryConfig = listOfLayerEntryConfig; + } + + /** *************************************************************************************************************************** + * Process recursively the list of layer entries to see if all of them are processed. + * + * @param {TypeLayerStatus} layerStatus The layer status to compare with the internal value of the config. + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration + * (default: this.listOfLayerEntryConfig). + * + * @returns {boolean} true when all layers are greater than or equal to the layerStatus parameter. + */ + obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo( + layerStatus: TypeLayerStatus, + listOfLayerEntryConfig: TypeListOfLayerEntryConfig = this.listOfLayerEntryConfig + ): boolean { + // Try to find a layer that is not greater than or equal to the layerStatus parameter. If you can, return false + return !listOfLayerEntryConfig.find((layerConfig: TypeLayerEntryConfig) => { + if (layerEntryIsGroupLayer(layerConfig)) + return !this.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo(layerStatus, layerConfig.listOfLayerEntryConfig); + return !layerConfig.IsGreaterThanOrEqualTo(layerStatus || 'newInstance'); + }); + } + + /** *************************************************************************************************************************** + * Process recursively the list of layer entries to initialize the registeredLayers object. + * + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries to process. + */ + obsoleteConfigInitRegisteredLayers( + layerApi: LayerApi, + listOfLayerEntryConfig: TypeListOfLayerEntryConfig = this.listOfLayerEntryConfig + ): void { + listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig, i) => { + if (layerApi.isRegistered(layerConfig)) { + this.layerLoadError.push({ + layer: layerConfig.layerPath, + loggerMessage: `Duplicate layerPath (mapId: ${this.mapId}, layerPath: ${layerConfig.layerPath})`, + }); + // Duplicat layer can't be kept because it has the same layer path than the first encontered layer. + delete listOfLayerEntryConfig[i]; + } else { + layerConfig.geoviewLayerInstance = this; + layerConfig.registerLayerConfig(); + } + if (layerEntryIsGroupLayer(layerConfig)) this.obsoleteConfigInitRegisteredLayers(layerApi, layerConfig.listOfLayerEntryConfig); + }); + } + + /** *************************************************************************************************************************** + * This method is used to create the layers specified in the listOfLayerEntryConfig attribute inherited from its parent. + * Normally, it is the second method called in the life cycle of a GeoView layer, the first one being the constructor. + * Its code is the same for all child classes. It must first validate that the olLayers attribute is null indicating + * that the method has never been called before for this layer. If this is not the case, an error message must be sent. + * Then, it calls the abstract method getAdditionalServiceDefinition. For example, when the child is a WFS service, this + * method executes the GetCapabilities request and saves the result in the metadata attribute of the class. It also process + * the layer's metadata for each layer in the listOfLayerEntryConfig tree in order to define the missing pieces of the layer's + * configuration. Layer's configuration can come from the configuration of the GeoView layer or from the information saved by + * the method processListOfLayerEntryMetadata, priority being given to the first of the two. When the GeoView layer does not + * have a service definition, the getAdditionalServiceDefinition method does nothing. + * + * Finally, the processListOfLayerEntryConfig is called to instantiate each layer identified by the listOfLayerEntryConfig + * attribute. This method will also register the layers to all layer sets that offer this possibility. For example, if a layer + * is queryable, it will subscribe to the details-panel and every time the user clicks on the map, the panel will ask the layer + * to return the descriptive information of all the features in a tolerance radius. This information will be used to populate + * the details-panel. + */ + async obsoleteConfigAndLayerCreateGeoViewLayers(): Promise { + if (this.olLayers === null) { + // Log + logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - createGeoViewLayers', this.listOfLayerEntryConfig); + + // Try to get a key for logging timings + let logTimingsKey; + if (this.listOfLayerEntryConfig.length > 0) logTimingsKey = `${this.mapId} | ${this.listOfLayerEntryConfig[0].layerPath}`; + + // Log + if (logTimingsKey) logger.logMarkerStart(logTimingsKey); + + // Get additional service and await + await this.#obsoleteConfigGetAdditionalServiceDefinition(); + + // Log the time it took thus far + if (logTimingsKey) logger.logMarkerCheck(logTimingsKey, 'to get additional service definition'); + + // Process list of layers and await + this.olLayers = await this.obsoleteConfigProcessListOfLayerEntryConfig(this.listOfLayerEntryConfig); + + // Log the time it took thus far + if (logTimingsKey) logger.logMarkerCheck(logTimingsKey, 'to process list of layer entry config'); + } else { + // Raise error + throw new GeoViewLayerCreatedTwiceError(this, this.mapId); + } + } + + /** *************************************************************************************************************************** + * This method reads from the metadataAccessPath additional information to complete the GeoView layer configuration. + * @private + */ + async #obsoleteConfigGetAdditionalServiceDefinition(): Promise { + try { + await this.obsoleteConfigFetchServiceMetadata(); + if (this.listOfLayerEntryConfig.length) await this.#obsoleteConfigValidateAndExtractLayerMetadata(); + } catch (error) { + // Log + logger.logError(error); } } /** *************************************************************************************************************************** - * Get the layerFilter that is associated to the layer. Returns undefined when the layer config can't be found using the layer - * path. - * - * @param {string} layerPath The layer path to the layer's configuration. + * This method Validate the list of layer configs and extract them in the geoview instance. + * @private + */ + async #obsoleteConfigValidateAndExtractLayerMetadata(): Promise { + try { + // Recursively process the configuration tree of layer entries by removing layers in error and processing valid layers. + this.obsoleteConfigValidateListOfLayerEntryConfig(this.listOfLayerEntryConfig); + await this.#obsoleteConfigProcessListOfLayerEntryMetadata(this.listOfLayerEntryConfig); + } catch (error) { + // Log + logger.logError(error); + } + } + + /** *************************************************************************************************************************** + * This method reads the service metadata from the metadataAccessPath. * - * @returns {string | undefined} The filter associated to the layer or undefined. + * @returns {Promise} A promise that the execution is completed. */ - getLayerFilter(layerPath: string): string | undefined { - const layerConfig = this.getLayerConfig(layerPath); - return layerConfig?.olLayer?.get('layerFilter'); + protected async obsoleteConfigFetchServiceMetadata(): Promise { + const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); + if (metadataUrl) { + try { + const metadataString = await getXMLHttpRequest(`${metadataUrl}?f=json`); + if (metadataString === '{}') this.metadata = null; + else { + this.metadata = toJsonObject(JSON.parse(metadataString)); + const { copyrightText } = this.metadata; + if (copyrightText) this.attributions.push(copyrightText as string); + } + } catch (error) { + // Log + logger.logError(error); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + } + } } /** *************************************************************************************************************************** - * Get the layerFilter that is associated to the layer. Returns undefined when the layer config can't be found using the layer - * path. + * This method recursively validates the configuration of the layer entries to ensure that each layer is correctly defined. If + * necessary, additional code can be executed in the child method to complete the layer configuration. * - * @param {string} layerPath The layer path to the layer's configuration. + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. + */ + protected abstract obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void; + + /** *************************************************************************************************************************** + * This method processes recursively the metadata of each layer in the "layer list" configuration. * - * @returns {TimeDimension} The temporal dimension associated to the layer or undefined. + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layers to process. + * + * @returns {Promise} A promise that the execution is completed. + * @private */ - getTemporalDimension(layerPath: string): TimeDimension { - return this.layerTemporalDimension[layerPath]; + async #obsoleteConfigProcessListOfLayerEntryMetadata(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): Promise { + try { + const promisedAllLayerDone: Promise[] = []; + for (let i = 0; i < listOfLayerEntryConfig.length; i++) { + const layerConfig: TypeLayerEntryConfig = listOfLayerEntryConfig[i]; + if (layerEntryIsGroupLayer(layerConfig)) + if (layerConfig.isMetadataLayerGroup) promisedAllLayerDone.push(this.#obsoleteConfigProcessMetadataGroupLayer(layerConfig)); + // eslint-disable-next-line no-await-in-loop + else await this.#obsoleteConfigProcessListOfLayerEntryMetadata(layerConfig.listOfLayerEntryConfig); + else promisedAllLayerDone.push(this.obsoleteConfigProcessLayerMetadata(layerConfig)); + } + const arrayOfLayerConfigs = await Promise.all(promisedAllLayerDone); + arrayOfLayerConfigs.forEach((layerConfig) => { + if (layerConfig.layerStatus === 'error') { + const message = `Error while loading layer path "${layerConfig.layerPath})" on map "${this.mapId}"`; + this.layerLoadError.push({ layer: layerConfig.layerPath, loggerMessage: message }); + throw new Error(message); + } else { + // When we get here, we know that the metadata (if the service provide some) are processed. + // We need to signal to the layer sets that the 'processed' phase is done. + // GV TODO: For the moment, be aware that the layerStatus setter is doing a lot of things behind the scene. + // GV The layerStatus setter contains a lot of code and we will change it in favor of a method. + layerConfig.layerStatus = 'processed'; + } + }); + } catch (error) { + // Log + logger.logError(error); + } } /** *************************************************************************************************************************** - * Set the layerTemporalDimension for the layer identified by specified layerPath. + * This method is used to process metadata group layer entries. These layers behave as a GeoView group layer and also as a data + * layer (i.e. they have extent, visibility and query flag definition). Metadata group layers can be identified by + * the presence of an isMetadataLayerGroup attribute set to true. * - * @param {string} layerPath The layer path to the layer's configuration affected by the change. - * @param {TimeDimension} temporalDimension The value to assign to the layer temporal dimension property. + * @param {GroupLayerEntryConfig} layerConfig The layer entry configuration to process. + * + * @returns {Promise} A promise that the vector layer configuration has its metadata and group layers processed. + * @private */ - setTemporalDimension(layerPath: string, temporalDimension: TimeDimension): void { - this.layerTemporalDimension[layerPath] = temporalDimension; + async #obsoleteConfigProcessMetadataGroupLayer(layerConfig: GroupLayerEntryConfig): Promise { + try { + await this.obsoleteConfigProcessLayerMetadata(layerConfig); + await this.#obsoleteConfigProcessListOfLayerEntryMetadata(layerConfig.listOfLayerEntryConfig!); + layerConfig.layerStatus = 'processed'; + return layerConfig; + } catch (error) { + // Log + logger.logError(error); + } + return layerConfig; } /** *************************************************************************************************************************** - * Get the bounds of the layer represented in the layerConfig pointed to by the layerPath, returns updated bounds + * This method is used to process the layer's metadata. It will fill the empty outfields and aliasFields properties of the + * layer's configuration when applicable. * - * @param {string} layerPath The Layer path to the layer's configuration. - * @param {Extent | undefined} bounds The current bounding box to be adjusted. + * @param {TypeLayerEntryConfig} layerConfig The layer entry configuration to process. * - * @returns {Extent} The new layer bounding box. + * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected abstract getBounds(layerPath: string, bounds?: Extent): Extent | undefined; + protected obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { + if (!layerConfig.source) layerConfig.source = {}; + if (!layerConfig.source.featureInfo) layerConfig.source.featureInfo = { queryable: false }; + + return Promise.resolve(layerConfig); + } /** *************************************************************************************************************************** - * Compute the layer bounds or undefined if the result can not be obtained from the feature extents that compose the layer. If - * projectionCode is defined, returns the bounds in the specified projection otherwise use the map projection. The bounds are - * different from the extent. They are mainly used for display purposes to show the bounding box in which the data resides and - * to zoom in on the entire layer data. It is not used by openlayer to limit the display of data on the map. + * Process recursively the list of layer Entries to create the layers and the layer groups. * - * @param {string} layerPath The Layer path to the layer's configuration. - * @param {string | number | undefined} projectionCode Optional projection code to use for the returned bounds. Default to - * current projection. + * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries to process. + * @param {LayerGroup} layerGroup Optional layer group to use when we have many layers. The very first call to + * processListOfLayerEntryConfig must not provide a value for this parameter. It is defined for internal use. * - * @returns {Extent | undefined} The layer bounding box. + * @returns {Promise} The promise that the layers were processed. */ - calculateBounds(layerPath: string): Extent | undefined { + async obsoleteConfigProcessListOfLayerEntryConfig( + listOfLayerEntryConfig: TypeListOfLayerEntryConfig, + layerGroup?: LayerGroup + ): Promise { + // Log + logger.logTraceCore('ABSTRACT-GEOVIEW-LAYERS - processListOfLayerEntryConfig', listOfLayerEntryConfig); + try { - let bounds: Extent | undefined; - const processGroupLayerBounds = (listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void => { - listOfLayerEntryConfig.forEach((layerConfig) => { - if (layerEntryIsGroupLayer(layerConfig)) processGroupLayerBounds(layerConfig.listOfLayerEntryConfig); - else { - bounds = this.getBounds(layerConfig.layerPath, bounds); + if (listOfLayerEntryConfig.length === 0) return null; + if (listOfLayerEntryConfig.length === 1) { + if (layerEntryIsGroupLayer(listOfLayerEntryConfig[0])) { + const newLayerGroup = this.obsoleteConfigCreateLayerGroup(listOfLayerEntryConfig[0], listOfLayerEntryConfig[0].initialSettings!); + const groupReturned = await this.obsoleteConfigProcessListOfLayerEntryConfig( + listOfLayerEntryConfig[0].listOfLayerEntryConfig!, + newLayerGroup + ); + if (groupReturned) { + if (layerGroup) layerGroup.getLayers().push(groupReturned); + return groupReturned; } + this.layerLoadError.push({ + layer: listOfLayerEntryConfig[0].layerPath, + loggerMessage: `Unable to create group layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`, + }); + return null; + } + + if ((listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig).layerStatus === 'error') return null; + const { layerPath } = listOfLayerEntryConfig[0]; + const baseLayer = await this.obsoleteConfigProcessOneLayerEntry(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig); + if (baseLayer) { + this.obsoleteLayerAPIRegisterToLayerSets(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig); + if (layerGroup) layerGroup!.getLayers().push(baseLayer!); + return layerGroup || baseLayer; + } + this.layerLoadError.push({ + layer: listOfLayerEntryConfig[0].layerPath, + loggerMessage: `Unable to create layer ${listOfLayerEntryConfig[0].layerPath} on map ${this.mapId}`, }); - }; + this.getLayerConfig(layerPath)!.layerStatus = 'error'; + return null; + } - const initialLayerConfig = this.getLayerConfig(layerPath); - if (initialLayerConfig) { - if (Array.isArray(initialLayerConfig)) processGroupLayerBounds(initialLayerConfig); - else processGroupLayerBounds([initialLayerConfig]); + if (!layerGroup) { + // All children of this level in the tree have the same parent, so we use the first element of the array to retrieve the parent node. + layerGroup = this.obsoleteConfigCreateLayerGroup( + (listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig).parentLayerConfig as TypeLayerEntryConfig, + listOfLayerEntryConfig[0].initialSettings! + ); } + const promiseOfLayerCreated: Promise[] = []; + listOfLayerEntryConfig.forEach((layerConfig, i) => { + if (layerEntryIsGroupLayer(layerConfig)) { + const newLayerGroup = this.obsoleteConfigCreateLayerGroup(listOfLayerEntryConfig[i], listOfLayerEntryConfig[i].initialSettings!); + promiseOfLayerCreated.push(this.obsoleteConfigProcessListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!, newLayerGroup)); + } else if ((listOfLayerEntryConfig[i] as AbstractBaseLayerEntryConfig).layerStatus === 'error') + promiseOfLayerCreated.push(Promise.resolve(null)); + else { + promiseOfLayerCreated.push(this.obsoleteConfigProcessOneLayerEntry(layerConfig as AbstractBaseLayerEntryConfig)); + } + }); + const listOfLayerCreated = await Promise.all(promiseOfLayerCreated); + listOfLayerCreated.forEach((baseLayer, i) => { + const { layerPath } = listOfLayerEntryConfig[i]; + if (baseLayer) { + const layerConfig = baseLayer?.get('layerConfig') as AbstractBaseLayerEntryConfig; + if (layerConfig) { + if (!layerEntryIsGroupLayer(listOfLayerEntryConfig[i])) { + this.obsoleteLayerAPIRegisterToLayerSets(baseLayer.get('layerConfig') as AbstractBaseLayerEntryConfig); + } + layerGroup!.getLayers().push(baseLayer); + } + } else { + this.layerLoadError.push({ + layer: listOfLayerEntryConfig[i].layerPath, + loggerMessage: `Unable to create ${ + layerEntryIsGroupLayer(listOfLayerEntryConfig[i]) ? CONST_LAYER_ENTRY_TYPES.GROUP : '' + } layer ${listOfLayerEntryConfig[i].layerPath} on map ${this.mapId}`, + }); + this.getLayerConfig(layerPath)!.layerStatus = 'error'; + } + }); - return bounds; + return layerGroup!; } catch (error) { // Log - logger.logError(`Couldn't calculate bounds on layer ${layerPath}`, error); - return undefined; + logger.logError(error); + return null; } } + /** *************************************************************************************************************************** + * This method creates a GeoView layer using the definition provided in the layerConfig parameter. + * + * @param {AbstractBaseLayerEntryConfig} layerConfig Information needed to create the GeoView layer. + * + * @returns {Promise} The GeoView layer that has been created. + */ + protected obsoleteConfigProcessOneLayerEntry(layerConfig: AbstractBaseLayerEntryConfig): Promise { + // GV IMPORTANT: The processOneLayerEntry method of all the children must call this method to ensure that the flow of + // GV layerStatus values is correctly sequenced. + layerConfig.layerStatus = 'loading'; + return Promise.resolve(null); + } + + /** *************************************************************************************************************************** + * This method register the layer entry to layer sets. Nothing is done if the registration is already done. + * + * @param {AbstractBaseLayerEntryConfig} layerConfig The layer config to register. + */ + obsoleteLayerAPIRegisterToLayerSets(layerConfig: AbstractBaseLayerEntryConfig): void { + // TODO: Refactor - This function should be deleted eventually. It's up to the layer orchestrator to manage the layers. + // TO.DOCONT: The layer itself shouldn't know about it nor should have an explicit function mentioning the layer sets. + + // Register to layer sets that are already created. + // Emit the layer registration + this.#emitGeoViewLayerRegistration({ layerPath: layerConfig.layerPath, layerConfig, action: 'add' }); + } + + /** *************************************************************************************************************************** + * This method unregisters the layer from the layer sets. + * + * @param {AbstractBaseLayerEntryConfig} layerConfig The layer entry to register. + */ + obsoleteLayerAPIUnregisterFromLayerSets(layerConfig: AbstractBaseLayerEntryConfig): void { + // TODO: Refactor - This function should be deleted eventually. It's up to the layer orchestrator to manage the layers. + // TO.DOCONT: The layer itself shouldn't know about it nor should have an explicit function mentioning the layer sets. + + // Emit the layer unregistration + this.#emitGeoViewLayerRegistration({ layerPath: layerConfig.layerPath, layerConfig, action: 'remove' }); + } + + /** *************************************************************************************************************************** + * Set the layerTemporalDimension for the layer identified by specified layerPath. + * + * @param {string} layerPath The layer path to the layer's configuration affected by the change. + * @param {TimeDimension} temporalDimension The value to assign to the layer temporal dimension property. + */ + obsoleteConfigSetTemporalDimension(layerPath: string, temporalDimension: TimeDimension): void { + this.#obsoleteConfigLayerTemporalDimension[layerPath] = temporalDimension; + } + /** *************************************************************************************************************************** * Set the layerStatus code of all layers in the listOfLayerEntryConfig. * @@ -1450,9 +1459,14 @@ export abstract class AbstractGeoViewLayer { * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer's configuration. * @param {string} errorMessage The error message. */ - setAllLayerStatusTo(newStatus: TypeLayerStatus, listOfLayerEntryConfig: TypeListOfLayerEntryConfig, errorMessage?: string): void { + obsoleteConfigSetAllLayerStatusTo( + newStatus: TypeLayerStatus, + listOfLayerEntryConfig: TypeListOfLayerEntryConfig, + errorMessage?: string + ): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { - if (layerEntryIsGroupLayer(layerConfig)) this.setAllLayerStatusTo(newStatus, layerConfig.listOfLayerEntryConfig, errorMessage); + if (layerEntryIsGroupLayer(layerConfig)) + this.obsoleteConfigSetAllLayerStatusTo(newStatus, layerConfig.listOfLayerEntryConfig, errorMessage); else { if (layerConfig.layerStatus === 'error') return; layerConfig.layerStatus = newStatus; @@ -1472,9 +1486,9 @@ export abstract class AbstractGeoViewLayer { * * @param {string} layerPath The layerpath to the node we want to delete. */ - removeConfig(layerPath: string): void { + obsoleteLayerAPIRemoveConfig(layerPath: string): void { const layerConfigToRemove = this.getLayerConfig(layerPath) as AbstractBaseLayerEntryConfig; - if (layerConfigToRemove.entryType !== CONST_LAYER_ENTRY_TYPES.GROUP) this.unregisterFromLayerSets(layerConfigToRemove); + if (layerConfigToRemove.entryType !== CONST_LAYER_ENTRY_TYPES.GROUP) this.obsoleteLayerAPIUnregisterFromLayerSets(layerConfigToRemove); delete MapEventProcessor.getMapViewerLayerAPI(this.mapId).registeredLayers[layerPath]; } } diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts index dcadf7300c5..0378d5bd082 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts @@ -36,24 +36,26 @@ import { AppEventProcessor } from '@/api/event-processors/event-processor-childr * * @returns {Promise} A promise that the execution is completed. */ -export async function commonfetchServiceMetadata(this: EsriDynamic | EsriFeature): Promise { - const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); +export async function commonfetchServiceMetadata(geoviewLayer: EsriDynamic | EsriFeature): Promise { + const metadataUrl = getLocalizedValue(geoviewLayer.metadataAccessPath, AppEventProcessor.getDisplayLanguage(geoviewLayer.mapId)); if (metadataUrl) { try { const metadataString = await getXMLHttpRequest(`${metadataUrl}?f=json`); - if (metadataString === '{}') this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + if (metadataString === '{}') + geoviewLayer.obsoleteConfigSetAllLayerStatusTo('error', geoviewLayer.listOfLayerEntryConfig, 'Unable to read metadata'); else { - this.metadata = JSON.parse(metadataString) as TypeJsonObject; - if ('error' in this.metadata) throw new Error(`Error code = ${this.metadata.error.code}, ${this.metadata.error.message}`); - const { copyrightText } = this.metadata; - if (copyrightText) this.attributions.push(copyrightText as string); + geoviewLayer.metadata = JSON.parse(metadataString) as TypeJsonObject; + if ('error' in geoviewLayer.metadata) + throw new Error(`Error code = ${geoviewLayer.metadata.error.code}, ${geoviewLayer.metadata.error.message}`); + const { copyrightText } = geoviewLayer.metadata; + if (copyrightText) geoviewLayer.attributions.push(copyrightText as string); } } catch (error) { logger.logInfo('Unable to read metadata', error); - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + geoviewLayer.obsoleteConfigSetAllLayerStatusTo('error', geoviewLayer.listOfLayerEntryConfig, 'Unable to read metadata'); } } else { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + geoviewLayer.obsoleteConfigSetAllLayerStatusTo('error', geoviewLayer.listOfLayerEntryConfig, 'Unable to read metadata'); } } @@ -73,7 +75,7 @@ export function commonValidateListOfLayerEntryConfig( const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!(layerConfig as GroupLayerEntryConfig).listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -149,7 +151,7 @@ export function commonValidateListOfLayerEntryConfig( subLayerEntryConfig.registerLayerConfig(); }); - this.validateListOfLayerEntryConfig(newListOfLayerEntryConfig); + this.obsoleteConfigValidateListOfLayerEntryConfig(newListOfLayerEntryConfig); return; } @@ -228,9 +230,9 @@ export function commonProcessTemporalDimension( singleHandle?: boolean ): void { if (esriTimeDimension !== undefined) { - layer.layerTemporalDimension[layerConfig.layerPath] = DateMgt.createDimensionFromESRI( - Cast(esriTimeDimension), - singleHandle + layer.obsoleteConfigSetTemporalDimension( + layerConfig.layerPath, + DateMgt.createDimensionFromESRI(Cast(esriTimeDimension), singleHandle) ); } } diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts index d3569dcbd2a..f52a8532414 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-dynamic.ts @@ -46,6 +46,8 @@ import { commonValidateListOfLayerEntryConfig, } from '@/geo/layer/geoview-layers/esri-layer-common'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; type TypeFieldOfTheSameValue = { value: string | number | Date; nbOccurence: number }; type TypeQueryTree = { fieldValue: string | number | Date; nextField: TypeQueryTree }[]; @@ -137,8 +139,8 @@ export class EsriDynamic extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { - return commonfetchServiceMetadata.call(this); + protected override obsoleteConfigFetchServiceMetadata(): Promise { + return commonfetchServiceMetadata(this); } /** *************************************************************************************************************************** @@ -147,7 +149,7 @@ export class EsriDynamic extends AbstractGeoViewRaster { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { commonValidateListOfLayerEntryConfig.call(this, listOfLayerEntryConfig); } @@ -229,7 +231,9 @@ export class EsriDynamic extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { return commonProcessLayerMetadata.call(this, layerConfig); } @@ -240,10 +244,12 @@ export class EsriDynamic extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: EsriDynamicLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry( + layerConfig: EsriDynamicLayerEntryConfig + ): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const sourceOptions: SourceOptions = {}; sourceOptions.attributions = [(this.metadata!.copyrightText ? this.metadata!.copyrightText : '') as string]; sourceOptions.url = getLocalizedValue(layerConfig.source.dataAccessPath!, AppEventProcessor.getDisplayLanguage(this.mapId)); diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts index 7871d7b4086..f99b85f8258 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/esri-image.ts @@ -36,6 +36,7 @@ import { } from '@/geo/layer/geoview-layers/esri-layer-common'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; import { getLegendStyles } from '@/geo/utils/renderer/geoview-renderer'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; export interface TypeEsriImageLayerConfig extends TypeGeoviewLayerConfig { geoviewLayerType: typeof CONST_LAYER_TYPES.ESRI_IMAGE; @@ -208,11 +209,11 @@ export class EsriImage extends AbstractGeoViewRaster { * * @returns {TypeListOfLayerEntryConfig} A new list of layer entries configuration with deleted error layers. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -285,7 +286,9 @@ export class EsriImage extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { return commonProcessLayerMetadata.call(this, layerConfig); } @@ -296,10 +299,10 @@ export class EsriImage extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: EsriImageLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry(layerConfig: EsriImageLayerEntryConfig): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const sourceOptions: SourceOptions = {}; sourceOptions.attributions = [(this.metadata!.copyrightText ? this.metadata!.copyrightText : '') as string]; sourceOptions.url = getLocalizedValue(layerConfig.source.dataAccessPath!, AppEventProcessor.getDisplayLanguage(this.mapId)); diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts index bc6625e25a4..9dbe79f8c5a 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/image-static.ts @@ -94,11 +94,9 @@ export class ImageStatic extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { - const promisedExecution = new Promise((resolve) => { - resolve(); - }); - return promisedExecution; + protected override obsoleteConfigFetchServiceMetadata(): Promise { + // Return empty resolved promise + return Promise.resolve(); } /** *************************************************************************************************************************** @@ -197,11 +195,11 @@ export class ImageStatic extends AbstractGeoViewRaster { * * @returns {TypeListOfLayerEntryConfig} A new list of layer entries configuration with deleted error layers. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -249,8 +247,10 @@ export class ImageStatic extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: ImageStaticLayerEntryConfig): Promise { - await super.processOneLayerEntry(layerConfig); + protected override async obsoleteConfigProcessOneLayerEntry( + layerConfig: ImageStaticLayerEntryConfig + ): Promise { + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); if (!layerConfig?.source?.extent) throw new Error('Parameter extent is not defined in source element of layerConfig.'); const sourceOptions: SourceOptions = { diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts index a1abe21e483..ad5e5f94b2d 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/vector-tiles.ts @@ -30,8 +30,9 @@ import { api } from '@/app'; import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; import { VectorTilesLayerEntryConfig } from '@/core/utils/config/validation-classes/raster-validation-classes/vector-tiles-layer-entry-config'; import { logger } from '@/core/utils/logger'; -import { TileLayerEntryConfig } from '@/core/utils/config/validation-classes/tile-layer-entry-config'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; // TODO: Implement method to validate Vector Tiles service // TODO: Add more customization (minZoom, maxZoom, TMS) @@ -139,11 +140,11 @@ export class VectorTiles extends AbstractGeoViewRaster { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig?.listOfLayerEntryConfig?.length) { this.layerLoadError.push({ layer: layerPath, @@ -167,10 +168,12 @@ export class VectorTiles extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: VectorTilesLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry( + layerConfig: VectorTilesLayerEntryConfig + ): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const sourceOptions: SourceOptions = { url: getLocalizedValue(layerConfig.source.dataAccessPath as TypeLocalizedString, AppEventProcessor.getDisplayLanguage(this.mapId)), }; @@ -250,8 +253,11 @@ export class VectorTiles extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TileLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { if (this.metadata) { + const vectorLayerConfig = layerConfig as VectorTilesLayerEntryConfig; const { tileInfo } = this.metadata; const extent = this.metadata.fullExtent; const newTileGrid: TypeTileGrid = { @@ -261,7 +267,7 @@ export class VectorTiles extends AbstractGeoViewRaster { tileSize: [tileInfo.rows as number, tileInfo.cols as number], }; // eslint-disable-next-line no-param-reassign - layerConfig.source!.tileGrid = newTileGrid; + vectorLayerConfig.source!.tileGrid = newTileGrid; if (layerConfig.initialSettings?.extent) // eslint-disable-next-line no-param-reassign diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts index 7970615a1ce..83a9980e062 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/wms.ts @@ -117,7 +117,7 @@ export class WMS extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the execution is completed. */ - protected override async fetchServiceMetadata(): Promise { + protected override async obsoleteConfigFetchServiceMetadata(): Promise { const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); if (metadataUrl) { const metadataAccessPathIsXmlFile = metadataUrl.slice(-4).toLowerCase() === '.xml'; @@ -177,12 +177,12 @@ export class WMS extends AbstractGeoViewRaster { } this.processMetadataInheritance(); } catch (error) { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } } } } else { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } } @@ -201,7 +201,7 @@ export class WMS extends AbstractGeoViewRaster { const metadata: TypeJsonObject = parser.read(capabilitiesString); return metadata; } catch (error) { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); return null; } } @@ -236,10 +236,10 @@ export class WMS extends AbstractGeoViewRaster { }; setDataAccessPath(this.listOfLayerEntryConfig); } else { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } } catch (error) { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } } @@ -378,11 +378,11 @@ export class WMS extends AbstractGeoViewRaster { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig?.listOfLayerEntryConfig?.length) { this.layerLoadError.push({ layer: layerPath, @@ -407,7 +407,7 @@ export class WMS extends AbstractGeoViewRaster { } if ('Layer' in layerFound) { - this.createGroupLayer(layerFound, layerConfig as AbstractBaseLayerEntryConfig); + this.obsoleteConfigCreateGroupLayer(layerFound, layerConfig as AbstractBaseLayerEntryConfig); return; } @@ -426,7 +426,7 @@ export class WMS extends AbstractGeoViewRaster { * @param {TypeJsonObject} layer The dynamic group layer metadata. * @param {AbstractBaseLayerEntryConfig} layerConfig The layer configurstion associated to the dynamic group. */ - private createGroupLayer(layer: TypeJsonObject, layerConfig: AbstractBaseLayerEntryConfig): void { + private obsoleteConfigCreateGroupLayer(layer: TypeJsonObject, layerConfig: AbstractBaseLayerEntryConfig): void { // TODO: Refactor - createGroup is the same thing for all the layers type? group is a geoview structure. // TO.DOCONT: Should it be handle upper in abstract class to loop in structure and launch the creation of a leaf? const newListOfLayerEntryConfig: TypeListOfLayerEntryConfig = []; @@ -454,7 +454,7 @@ export class WMS extends AbstractGeoViewRaster { }; switchToGroupLayer.isMetadataLayerGroup = true; switchToGroupLayer.listOfLayerEntryConfig = newListOfLayerEntryConfig; - this.validateListOfLayerEntryConfig(newListOfLayerEntryConfig); + this.obsoleteConfigValidateListOfLayerEntryConfig(newListOfLayerEntryConfig); } /** **************************************************************************************************************************** @@ -491,10 +491,12 @@ export class WMS extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer | null} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: AbstractBaseLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry( + layerConfig: AbstractBaseLayerEntryConfig + ): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); // Log logger.logTraceCore('WMS - processOneLayerEntry', layerConfig.layerPath); @@ -576,7 +578,9 @@ export class WMS extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { if (geoviewEntryIsWMS(layerConfig)) { const layerCapabilities = this.getLayerMetadataEntry(layerConfig.layerId)!; this.layerMetadata[layerConfig.layerPath] = layerCapabilities; @@ -618,7 +622,7 @@ export class WMS extends AbstractGeoViewRaster { */ protected processTemporalDimension(wmsTimeDimension: TypeJsonObject, layerConfig: OgcWmsLayerEntryConfig): void { if (wmsTimeDimension !== undefined) { - this.layerTemporalDimension[layerConfig.layerPath] = DateMgt.createDimensionFromOGC(wmsTimeDimension); + this.obsoleteConfigSetTemporalDimension(layerConfig.layerPath, DateMgt.createDimensionFromOGC(wmsTimeDimension)); } } diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts b/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts index ce26533d69f..424bbf34dba 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/raster/xyz-tiles.ts @@ -22,6 +22,8 @@ import { Projection } from '@/geo/utils/projection'; import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor'; import { XYZTilesLayerEntryConfig } from '@/core/utils/config/validation-classes/raster-validation-classes/xyz-layer-entry-config'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; // ? Do we keep this TODO ? Dynamic parameters can be placed on the dataAccessPath and initial settings can be used on xyz-tiles. // TODO: Implement method to validate XYZ tile service @@ -125,11 +127,11 @@ export class XYZTiles extends AbstractGeoViewRaster { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -177,10 +179,10 @@ export class XYZTiles extends AbstractGeoViewRaster { * * @returns {TypeBaseRasterLayer} The GeoView raster layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: XYZTilesLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry(layerConfig: XYZTilesLayerEntryConfig): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const sourceOptions: SourceOptions = { url: getLocalizedValue(layerConfig.source.dataAccessPath as TypeLocalizedString, AppEventProcessor.getDisplayLanguage(this.mapId)), }; @@ -229,7 +231,9 @@ export class XYZTiles extends AbstractGeoViewRaster { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { if (this.metadata) { const metadataLayerConfigFound = Cast(this.metadata?.listOfLayerEntryConfig).find( (metadataLayerConfig) => metadataLayerConfig.layerId === layerConfig.layerId diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts index 36d84d44281..0c169b36295 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/abstract-geoview-vector.ts @@ -67,7 +67,7 @@ export abstract class AbstractGeoViewVector extends AbstractGeoViewLayer { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected abstract override validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void; + protected abstract override obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void; /** *************************************************************************************************************************** * Extract the type of the specified field from the metadata. If the type can not be found, return 'string'. @@ -96,10 +96,10 @@ export abstract class AbstractGeoViewVector extends AbstractGeoViewLayer { * * @returns {Promise} The GeoView base layer that has been created. */ - protected override async processOneLayerEntry(layerConfig: AbstractBaseLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessOneLayerEntry(layerConfig: AbstractBaseLayerEntryConfig): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const vectorSource = this.createVectorSource(layerConfig); const vectorLayer = this.createVectorLayer(layerConfig as VectorLayerEntryConfig, vectorSource); return Promise.resolve(vectorLayer); diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts index 5842c1ef266..85982d6821e 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/csv.ts @@ -27,6 +27,7 @@ import { CsvLayerEntryConfig } from '@/core/utils/config/validation-classes/vect import { VectorLayerEntryConfig } from '@/core/utils/config/validation-classes/vector-layer-entry-config'; import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; // GV: CONFIG EXTRACTION // GV: This section of code was extracted and copied to the geoview-config package @@ -111,8 +112,8 @@ export class CSV extends AbstractGeoViewVector { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { - // Return resolved promise + protected override obsoleteConfigFetchServiceMetadata(): Promise { + // Return empty resolved promise return Promise.resolve(); } @@ -122,11 +123,11 @@ export class CSV extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -153,7 +154,9 @@ export class CSV extends AbstractGeoViewVector { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: VectorLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { return Promise.resolve(layerConfig); } diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts index b0c3e313177..757271189dd 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/esri-feature.ts @@ -29,6 +29,7 @@ import { commonValidateListOfLayerEntryConfig, } from '@/geo/layer/geoview-layers/esri-layer-common'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; export interface TypeSourceEsriFeatureInitialConfig extends Omit { format: 'EsriJSON'; @@ -106,8 +107,8 @@ export class EsriFeature extends AbstractGeoViewVector { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { - return commonfetchServiceMetadata.call(this); + protected override obsoleteConfigFetchServiceMetadata(): Promise { + return commonfetchServiceMetadata(this); } /** *************************************************************************************************************************** @@ -116,7 +117,7 @@ export class EsriFeature extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { commonValidateListOfLayerEntryConfig.call(this, listOfLayerEntryConfig); } @@ -198,7 +199,9 @@ export class EsriFeature extends AbstractGeoViewVector { * * @returns {Promise} A promise that the layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: TypeLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { return commonProcessLayerMetadata.call(this, layerConfig); } diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts index c166a683ced..e602fe8ea3d 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geojson.ts @@ -26,6 +26,7 @@ import { GeoJSONLayerEntryConfig } from '@/core/utils/config/validation-classes/ import { VectorLayerEntryConfig } from '@/core/utils/config/validation-classes/vector-layer-entry-config'; import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; export interface TypeSourceGeoJSONInitialConfig extends Omit { format: 'GeoJSON'; @@ -102,11 +103,11 @@ export class GeoJSON extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -155,18 +156,21 @@ export class GeoJSON extends AbstractGeoViewVector { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override processLayerMetadata(layerConfig: VectorLayerEntryConfig): Promise { + protected override obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { if (this.metadata) { const metadataLayerList = Cast(this.metadata?.listOfLayerEntryConfig); const layerMetadataFound = metadataLayerList.find( (layerMetadata) => layerMetadata.layerId === layerConfig.layerId && layerMetadata.layerIdExtension === layerConfig.layerIdExtension ); if (layerMetadataFound) { + const vectorLayerConfig = layerConfig as VectorLayerEntryConfig; this.layerMetadata[layerConfig.layerPath] = toJsonObject(layerMetadataFound); layerConfig.layerName = layerConfig.layerName || layerMetadataFound.layerName; layerConfig.source = defaultsDeep(layerConfig.source, layerMetadataFound.source); layerConfig.initialSettings = defaultsDeep(layerConfig.initialSettings, layerMetadataFound.initialSettings); - layerConfig.style = defaultsDeep(layerConfig.style, layerMetadataFound.style); + vectorLayerConfig.style = defaultsDeep(vectorLayerConfig.style, layerMetadataFound.style); // When the dataAccessPath stored in the layerConfig.source object is equal to the root of the metadataAccessPath with a // layerId ending, chances are that it was set by the config-validation because of an empty dataAcessPath value in the config. // This situation means that we want to use the dataAccessPath found in the metadata if it is set, otherwise we will keep the diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts index 34be68234b7..4d796fe5636 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/geopackage.ts @@ -130,8 +130,8 @@ export class GeoPackage extends AbstractGeoViewVector { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { - // Return resolved promise + protected override obsoleteConfigFetchServiceMetadata(): Promise { + // Return empty resolved promise return Promise.resolve(); } @@ -141,11 +141,11 @@ export class GeoPackage extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -170,16 +170,19 @@ export class GeoPackage extends AbstractGeoViewVector { * @returns {Promise} The promise that the layers were processed. */ // TODO: Question - Is this function still used or should it be removed in favor of the mother class implementation? - override processListOfLayerEntryConfig( + override obsoleteConfigProcessListOfLayerEntryConfig( listOfLayerEntryConfig: TypeListOfLayerEntryConfig, layerGroup?: LayerGroup ): Promise { const promisedListOfLayerEntryProcessed = new Promise((resolve) => { // Single group layer handled recursively if (listOfLayerEntryConfig.length === 1 && layerEntryIsGroupLayer(listOfLayerEntryConfig[0])) { - const newLayerGroup = GeoPackage.createLayerGroup(listOfLayerEntryConfig[0], listOfLayerEntryConfig[0].initialSettings!); + const newLayerGroup = GeoPackage.obsoleteConfigCreateLayerGroup( + listOfLayerEntryConfig[0], + listOfLayerEntryConfig[0].initialSettings! + ); - this.processListOfLayerEntryConfig(listOfLayerEntryConfig[0].listOfLayerEntryConfig!, newLayerGroup) + this.obsoleteConfigProcessListOfLayerEntryConfig(listOfLayerEntryConfig[0].listOfLayerEntryConfig!, newLayerGroup) .then((groupReturned) => { if (groupReturned) { if (layerGroup) layerGroup.getLayers().push(groupReturned); @@ -199,15 +202,15 @@ export class GeoPackage extends AbstractGeoViewVector { // Multiple layer configs are processed individually and added to layer group } else if (listOfLayerEntryConfig.length > 1) { if (!layerGroup) - layerGroup = GeoPackage.createLayerGroup( + layerGroup = GeoPackage.obsoleteConfigCreateLayerGroup( listOfLayerEntryConfig[0].parentLayerConfig as TypeLayerEntryConfig, listOfLayerEntryConfig[0].initialSettings! ); listOfLayerEntryConfig.forEach((layerConfig) => { if (layerEntryIsGroupLayer(layerConfig)) { - const newLayerGroup = GeoPackage.createLayerGroup(layerConfig, layerConfig.initialSettings!); - this.processListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!, newLayerGroup) + const newLayerGroup = GeoPackage.obsoleteConfigCreateLayerGroup(layerConfig, layerConfig.initialSettings!); + this.obsoleteConfigProcessListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!, newLayerGroup) .then((groupReturned) => { if (groupReturned) { layerGroup!.getLayers().push(groupReturned); @@ -224,7 +227,7 @@ export class GeoPackage extends AbstractGeoViewVector { logger.logPromiseFailed('processListOfLayerEntryConfig (2) in processListOfLayerEntryConfig in GeoPackage', error); }); } else { - this.processOneLayerEntry(layerConfig as AbstractBaseLayerEntryConfig) + this.obsoleteConfigProcessOneLayerEntry(layerConfig as AbstractBaseLayerEntryConfig) .then((layers) => { if (layers) { layerGroup!.getLayers().push(layers); @@ -246,7 +249,7 @@ export class GeoPackage extends AbstractGeoViewVector { if (layerGroup) resolve(layerGroup); // Single non-group config } else { - this.processOneLayerEntry(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig, layerGroup) + this.obsoleteConfigProcessOneLayerEntry(listOfLayerEntryConfig[0] as AbstractBaseLayerEntryConfig, layerGroup) .then((layer) => { if (layer) { listOfLayerEntryConfig[0].layerStatus = 'processed'; @@ -571,13 +574,13 @@ export class GeoPackage extends AbstractGeoViewVector { * * @returns {Promise} The GeoView base layer that has been created. */ - protected override async processOneLayerEntry( + protected override async obsoleteConfigProcessOneLayerEntry( layerConfig: AbstractBaseLayerEntryConfig, layerGroup?: LayerGroup ): Promise { // GV IMPORTANT: The processOneLayerEntry method must call the corresponding method of its parent to ensure that the flow of // GV layerStatus values is correctly sequenced. - await super.processOneLayerEntry(layerConfig); + await super.obsoleteConfigProcessOneLayerEntry(layerConfig); const promisedLayers = new Promise((resolve) => { this.extractGeopackageData(layerConfig) .then(([layers, slds]) => { @@ -604,7 +607,7 @@ export class GeoPackage extends AbstractGeoViewVector { } else { layerConfig.entryType = CONST_LAYER_ENTRY_TYPES.GROUP; (layerConfig as TypeLayerEntryConfig).listOfLayerEntryConfig = []; - const newLayerGroup = GeoPackage.createLayerGroup(layerConfig, layerConfig.initialSettings!); + const newLayerGroup = GeoPackage.obsoleteConfigCreateLayerGroup(layerConfig, layerConfig.initialSettings!); for (let i = 0; i < layers.length; i++) { const newLayerEntryConfig = cloneDeep(layerConfig) as AbstractBaseLayerEntryConfig; newLayerEntryConfig.layerId = layers[i].name; diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts index eef6d177540..3da25397cdd 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/ogc-feature.ts @@ -28,6 +28,7 @@ import { VectorLayerEntryConfig } from '@/core/utils/config/validation-classes/v import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; import { getLocalizedValue } from '@/core/utils/utilities'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; export interface TypeSourceOgcFeatureInitialConfig extends TypeVectorSourceInitialConfig { format: 'featureAPI'; @@ -126,7 +127,7 @@ export class OgcFeature extends AbstractGeoViewVector { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { + protected override obsoleteConfigFetchServiceMetadata(): Promise { const promisedExecution = new Promise((resolve) => { const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); if (metadataUrl) { @@ -138,12 +139,12 @@ export class OgcFeature extends AbstractGeoViewVector { resolve(); }) .catch((reason) => { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); logger.logError('Unable to fetch metadata', this.metadataAccessPath, reason); resolve(); }); } else { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } }); return promisedExecution; @@ -155,11 +156,11 @@ export class OgcFeature extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -222,7 +223,9 @@ export class OgcFeature extends AbstractGeoViewVector { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override async processLayerMetadata(layerConfig: VectorLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { try { const metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); if (metadataUrl) { @@ -231,8 +234,9 @@ export class OgcFeature extends AbstractGeoViewVector { : `${metadataUrl}/collections/${String(layerConfig.layerId)}/queryables?f=json`; const queryResult = await axios.get(queryUrl); if (queryResult.data.properties) { + const vectorLayerConfig = layerConfig as VectorLayerEntryConfig; this.layerMetadata[layerConfig.layerPath] = queryResult.data.properties; - OgcFeature.#processFeatureInfoConfig(queryResult.data.properties, layerConfig); + OgcFeature.#processFeatureInfoConfig(queryResult.data.properties, vectorLayerConfig); } } } catch (error) { diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts b/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts index be7f02a7a5a..291a5a9e644 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/vector/wfs.ts @@ -27,6 +27,8 @@ import { WfsLayerEntryConfig } from '@/core/utils/config/validation-classes/vect import { VectorLayerEntryConfig } from '@/core/utils/config/validation-classes/vector-layer-entry-config'; import { AbstractBaseLayerEntryConfig } from '@/core/utils/config/validation-classes/abstract-base-layer-entry-config'; import { AppEventProcessor } from '@/api/event-processors/event-processor-children/app-event-processor'; +import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; +import { EsriFeatureLayerEntryConfig } from '@/core/utils/config/validation-classes/vector-validation-classes/esri-feature-layer-entry-config'; export interface TypeSourceWFSVectorInitialConfig extends TypeVectorSourceInitialConfig { format: 'WFS'; @@ -121,7 +123,7 @@ export class WFS extends AbstractGeoViewVector { * * @returns {Promise} A promise that the execution is completed. */ - protected override fetchServiceMetadata(): Promise { + protected override obsoleteConfigFetchServiceMetadata(): Promise { const promisedExecution = new Promise((resolve) => { let metadataUrl = getLocalizedValue(this.metadataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)) as string; @@ -134,7 +136,7 @@ export class WFS extends AbstractGeoViewVector { getXMLHttpRequest(`${metadataUrl}${getCapabilitiesUrl}`) .then((metadataString) => { if (metadataString === '{}') { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } else { // need to pass a xmldom to xmlToJson const xmlDOMCapabilities = new DOMParser().parseFromString(metadataString, 'text/xml'); @@ -148,12 +150,12 @@ export class WFS extends AbstractGeoViewVector { } }) .catch((reason) => { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); logger.logError('Unableto fetch metadata', this.metadataAccessPath, reason); resolve(); }); } else { - this.setAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); + this.obsoleteConfigSetAllLayerStatusTo('error', this.listOfLayerEntryConfig, 'Unable to read metadata'); } }); return promisedExecution; @@ -165,11 +167,11 @@ export class WFS extends AbstractGeoViewVector { * * @param {TypeListOfLayerEntryConfig} listOfLayerEntryConfig The list of layer entries configuration to validate. */ - protected validateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { + protected obsoleteConfigValidateListOfLayerEntryConfig(listOfLayerEntryConfig: TypeListOfLayerEntryConfig): void { listOfLayerEntryConfig.forEach((layerConfig: TypeLayerEntryConfig) => { const { layerPath } = layerConfig; if (layerEntryIsGroupLayer(layerConfig)) { - this.validateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); + this.obsoleteConfigValidateListOfLayerEntryConfig(layerConfig.listOfLayerEntryConfig!); if (!layerConfig.listOfLayerEntryConfig.length) { this.layerLoadError.push({ layer: layerPath, @@ -235,7 +237,9 @@ export class WFS extends AbstractGeoViewVector { * * @returns {Promise} A promise that the vector layer configuration has its metadata processed. */ - protected override async processLayerMetadata(layerConfig: VectorLayerEntryConfig): Promise { + protected override async obsoleteConfigProcessLayerMetadata( + layerConfig: AbstractBaseLayerEntryConfig | GroupLayerEntryConfig + ): Promise { try { let queryUrl = getLocalizedValue(layerConfig.source!.dataAccessPath, AppEventProcessor.getDisplayLanguage(this.mapId)); @@ -260,11 +264,12 @@ export class WFS extends AbstractGeoViewVector { this.version }&outputFormat=${encodeURIComponent(outputFormat as string)}&typeName=${layerConfig.layerId}`; + const esriFeatureLayerConfig = layerConfig as EsriFeatureLayerEntryConfig; if (describeFeatureUrl && outputFormat === 'application/json') { const layerMetadata = (await (await fetch(describeFeatureUrl)).json()) as TypeJsonObject; if (Array.isArray(layerMetadata.featureTypes) && Array.isArray(layerMetadata.featureTypes[0].properties)) { this.layerMetadata[layerConfig.layerPath] = layerMetadata.featureTypes[0].properties; - this.#processFeatureInfoConfig(layerMetadata.featureTypes[0].properties as TypeJsonArray, layerConfig); + this.#processFeatureInfoConfig(layerMetadata.featureTypes[0].properties as TypeJsonArray, esriFeatureLayerConfig); } } else if (describeFeatureUrl && outputFormat.toUpperCase().includes('XML')) { const layerMetadata = (await (await fetch(describeFeatureUrl)).text()) as string; @@ -288,7 +293,7 @@ export class WFS extends AbstractGeoViewVector { }); this.layerMetadata[layerConfig.layerPath] = featureTypeProperties as TypeJsonObject; - this.#processFeatureInfoConfig(featureTypeProperties as TypeJsonArray, layerConfig); + this.#processFeatureInfoConfig(featureTypeProperties as TypeJsonArray, esriFeatureLayerConfig); } } } catch (error) { diff --git a/packages/geoview-core/src/geo/layer/layer-sets/legends-layer-set.ts b/packages/geoview-core/src/geo/layer/layer-sets/legends-layer-set.ts index 3ab316e778a..53523dc758c 100644 --- a/packages/geoview-core/src/geo/layer/layer-sets/legends-layer-set.ts +++ b/packages/geoview-core/src/geo/layer/layer-sets/legends-layer-set.ts @@ -75,10 +75,6 @@ export class LegendsLayerSet extends AbstractLayerSet { // Log logger.logPromiseFailed('legendPromise in onProcessLayerStatusChanged in legendsLayerSet', error); }); - - // config file could not determine if the layer is queryable, can it be done using the metadata? let's try - // ? Trying to comment this line to see if it's good, don't understand the comment line just above this line - // layerConfig.geoviewLayerInstance?.registerToLayerSets(layerConfig as AbstractBaseLayerEntryConfig); } if (layerExists || layerStatus === 'loaded') { diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts index d5f6406a99b..51f0a686757 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -212,14 +212,14 @@ export class LayerApi { .map((promise) => promise as PromiseFulfilledResult) .forEach((promise) => { // For each layer - promise.value.forEach((geocoreGVLayer) => { + promise.value.forEach((geoviewLayerConfig) => { try { // Generate array of layer order information - const layerInfos = LayerApi.generateArrayOfLayerOrderInfo(geocoreGVLayer); + const layerInfos = LayerApi.generateArrayOfLayerOrderInfo(geoviewLayerConfig); orderedLayerInfos.push(...layerInfos); // Add it - const addedResult = this.addGeoviewLayer(geocoreGVLayer); + const addedResult = this.addGeoviewLayer(geoviewLayerConfig); // If processed far enough to have a result with a promise if (addedResult) { @@ -243,7 +243,7 @@ export class LayerApi { }); } else { // Layer failed to get created - throw new GeoViewLayerNotCreatedError(geocoreGVLayer.geoviewLayerId, this.mapId); + throw new GeoViewLayerNotCreatedError(geoviewLayerConfig.geoviewLayerId, this.mapId); } } catch (error) { // Layer encountered a generic error when being created and added to the map @@ -415,13 +415,13 @@ export class LayerApi { // Prepare mandatory registrations // TODO: Refactor - this shouldn't have to be mandatory! And not a function of the layer. - layerBeingAdded.initRegisteredLayers(this); + layerBeingAdded.obsoleteConfigInitRegisteredLayers(this); // Create a promise about the layer will be on the map const promiseLayer = new Promise((resolve, reject) => { // Continue the addition process layerBeingAdded! - .createGeoViewLayers() + .obsoleteConfigAndLayerCreateGeoViewLayers() .then(() => { // Add the layer on the map this.#addToMap(layerBeingAdded!); @@ -468,7 +468,7 @@ export class LayerApi { } // If all layer status are good - if (!geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('error')) { + if (!geoviewLayer.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('error')) { // Add the OpenLayers layer to the map officially this.mapViewer.map.addLayer(geoviewLayer.olLayers!); } @@ -751,7 +751,7 @@ export class LayerApi { const pathBeginningAreEqual = partialLayerPathNodes.reduce((areEqual, partialLayerPathNode, nodeIndex) => { return areEqual && partialLayerPathNode === completeLayerPathNodes[nodeIndex]; }, true); - if (pathBeginningAreEqual) this.geoviewLayer(completeLayerPath).removeConfig(completeLayerPath); + if (pathBeginningAreEqual) this.geoviewLayer(completeLayerPath).obsoleteLayerAPIRemoveConfig(completeLayerPath); }); if (listOfLayerEntryConfigAffected) listOfLayerEntryConfigAffected.splice(indexToDelete!, 1); @@ -860,7 +860,7 @@ export class LayerApi { // Wait for the processed phase await whenThisThen( () => { - return geoviewLayerConfig.allLayerStatusAreGreaterThanOrEqualTo('processed'); + return geoviewLayerConfig.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('processed'); }, timeout, checkFrequency diff --git a/packages/geoview-core/src/geo/map/map-schema-types.ts b/packages/geoview-core/src/geo/map/map-schema-types.ts index 75b58f7d6a2..d0c5925556b 100644 --- a/packages/geoview-core/src/geo/map/map-schema-types.ts +++ b/packages/geoview-core/src/geo/map/map-schema-types.ts @@ -17,6 +17,7 @@ import { TileLayerEntryConfig } from '@/core/utils/config/validation-classes/til import { GroupLayerEntryConfig } from '@/core/utils/config/validation-classes/group-layer-entry-config'; import { ConfigBaseClass } from '@/core/utils/config/validation-classes/config-base-class'; import { TypeJsonValue } from '@/core/types/global-types'; +import { VectorTilesLayerEntryConfig } from '@/core/utils/config/validation-classes/raster-validation-classes/vector-tiles-layer-entry-config'; // #region UTILITIES TYPES @@ -488,7 +489,7 @@ export interface TypeVectorTileSourceInitialConfig extends TypeBaseSourceVectorI export type TypeLayerEntryConfig = | AbstractBaseLayerEntryConfig | VectorLayerEntryConfig - | VectorLayerEntryConfig + | VectorTilesLayerEntryConfig | OgcWmsLayerEntryConfig | EsriDynamicLayerEntryConfig | EsriImageLayerEntryConfig diff --git a/packages/geoview-core/src/geo/map/map-viewer.ts b/packages/geoview-core/src/geo/map/map-viewer.ts index abecfeeb3c9..fc2e9ea99ba 100644 --- a/packages/geoview-core/src/geo/map/map-viewer.ts +++ b/packages/geoview-core/src/geo/map/map-viewer.ts @@ -475,7 +475,7 @@ export class MapViewer { let allGeoviewLayerRegistered = this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0; Object.values(geoviewLayers).forEach((geoviewLayer) => { - const layerIsRegistered = geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('registered'); + const layerIsRegistered = geoviewLayer.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('registered'); if (!layerIsRegistered) logger.logTraceDetailed('checkMapReady - wating on layer registration...', geoviewLayer.geoviewLayerId); allGeoviewLayerRegistered &&= layerIsRegistered; }); @@ -576,7 +576,7 @@ export class MapViewer { let allGeoviewLayerLoaded = this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0; Object.values(geoviewLayers).forEach((geoviewLayer) => { - const layerIsLoaded = geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('processed'); + const layerIsLoaded = geoviewLayer.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('processed'); if (!layerIsLoaded) logger.logTraceDetailed('checkMapLayersProcessed - waiting on layer processed...', geoviewLayer.geoviewLayerId); allGeoviewLayerLoaded &&= layerIsLoaded; @@ -632,7 +632,7 @@ export class MapViewer { let allGeoviewLayerLoaded = this.mapFeaturesConfig.map.listOfGeoviewLayerConfig?.length === 0 || Object.keys(geoviewLayers).length !== 0; Object.values(geoviewLayers).forEach((geoviewLayer) => { - const layerIsLoaded = geoviewLayer.allLayerStatusAreGreaterThanOrEqualTo('loaded'); + const layerIsLoaded = geoviewLayer.obsoleteConfigAllLayerStatusAreGreaterThanOrEqualTo('loaded'); if (!layerIsLoaded) logger.logTraceDetailed('checkMapLayersLoaded - waiting on layer loaded/error...', geoviewLayer.geoviewLayerId); allGeoviewLayerLoaded &&= layerIsLoaded; diff --git a/packages/geoview-time-slider/src/index.tsx b/packages/geoview-time-slider/src/index.tsx index acd6bc601c9..15dc8971b02 100644 --- a/packages/geoview-time-slider/src/index.tsx +++ b/packages/geoview-time-slider/src/index.tsx @@ -131,18 +131,18 @@ class TimeSliderPlugin extends FooterPlugin { // TO.DOCONT: using event listeners, not at Plugin creation. MapEventProcessor.getMapViewerLayerAPI(this.pluginProps.mapId) .geoviewLayer(obj.layerPaths[0]) - .setTemporalDimension(obj.layerPaths[0], timeDimension); + .obsoleteConfigSetTemporalDimension(obj.layerPaths[0], timeDimension); } // Set override default value under time dimension if applicable if (obj.defaultValue) { const layerPath = obj.layerPaths[0]; - const timeDimension = MapEventProcessor.getMapViewerLayerAPI(this.pluginProps.mapId).geoviewLayer(layerPath).layerTemporalDimension[ - layerPath - ]; + const timeDimension = MapEventProcessor.getMapViewerLayerAPI(this.pluginProps.mapId) + .geoviewLayer(layerPath) + .getTemporalDimension(layerPath); MapEventProcessor.getMapViewerLayerAPI(this.pluginProps.mapId) .geoviewLayer(layerPath) - .setTemporalDimension(layerPath, { + .obsoleteConfigSetTemporalDimension(layerPath, { ...timeDimension, default: obj.defaultValue, }); @@ -194,8 +194,8 @@ class TimeSliderPlugin extends FooterPlugin { * @private */ #filterTimeSliderLayers(layerPaths: string[]): string[] { - const filteredLayerPaths = layerPaths.filter( - (layerPath) => this.mapViewer().layer.geoviewLayers[layerPath.split('/')[0]].layerTemporalDimension[layerPath] + const filteredLayerPaths = layerPaths.filter((layerPath) => + this.mapViewer().layer.geoviewLayers[layerPath.split('/')[0]].getTemporalDimension(layerPath) ); return filteredLayerPaths; }